1 /*
2  * nghttp3
3  *
4  * Copyright (c) 2019 nghttp3 contributors
5  * Copyright (c) 2015 nghttp2 contributors
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining
8  * a copy of this software and associated documentation files (the
9  * "Software"), to deal in the Software without restriction, including
10  * without limitation the rights to use, copy, modify, merge, publish,
11  * distribute, sublicense, and/or sell copies of the Software, and to
12  * permit persons to whom the Software is furnished to do so, subject to
13  * the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be
16  * included in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  */
26 #include "nghttp3_http.h"
27 
28 #include <string.h>
29 #include <assert.h>
30 
31 #include "nghttp3_stream.h"
32 #include "nghttp3_macro.h"
33 #include "nghttp3_conv.h"
34 
downcase(uint8_t c)35 static uint8_t downcase(uint8_t c) {
36   return 'A' <= c && c <= 'Z' ? (uint8_t)(c - 'A' + 'a') : c;
37 }
38 
memieq(const void * a,const void * b,size_t n)39 static int memieq(const void *a, const void *b, size_t n) {
40   size_t i;
41   const uint8_t *aa = a, *bb = b;
42 
43   for (i = 0; i < n; ++i) {
44     if (downcase(aa[i]) != downcase(bb[i])) {
45       return 0;
46     }
47   }
48   return 1;
49 }
50 
51 #define lstrieq(A, B, N) ((sizeof((A)) - 1) == (N) && memieq((A), (B), (N)))
52 
parse_uint(const uint8_t * s,size_t len)53 static int64_t parse_uint(const uint8_t *s, size_t len) {
54   int64_t n = 0;
55   size_t i;
56   if (len == 0) {
57     return -1;
58   }
59   for (i = 0; i < len; ++i) {
60     if ('0' <= s[i] && s[i] <= '9') {
61       if (n > INT64_MAX / 10) {
62         return -1;
63       }
64       n *= 10;
65       if (n > INT64_MAX - (s[i] - '0')) {
66         return -1;
67       }
68       n += s[i] - '0';
69       continue;
70     }
71     return -1;
72   }
73   return n;
74 }
75 
lws(const uint8_t * s,size_t n)76 static int lws(const uint8_t *s, size_t n) {
77   size_t i;
78   for (i = 0; i < n; ++i) {
79     if (s[i] != ' ' && s[i] != '\t') {
80       return 0;
81     }
82   }
83   return 1;
84 }
85 
check_pseudo_header(nghttp3_http_state * http,const nghttp3_qpack_nv * nv,int flag)86 static int check_pseudo_header(nghttp3_http_state *http,
87                                const nghttp3_qpack_nv *nv, int flag) {
88   if (http->flags & flag) {
89     return 0;
90   }
91   if (lws(nv->value->base, nv->value->len)) {
92     return 0;
93   }
94   http->flags = (uint16_t)(http->flags | flag);
95   return 1;
96 }
97 
expect_response_body(nghttp3_http_state * http)98 static int expect_response_body(nghttp3_http_state *http) {
99   return (http->flags & NGHTTP3_HTTP_FLAG_METH_HEAD) == 0 &&
100          http->status_code / 100 != 1 && http->status_code != 304 &&
101          http->status_code != 204;
102 }
103 
104 /* For "http" or "https" URIs, OPTIONS request may have "*" in :path
105    header field to represent system-wide OPTIONS request.  Otherwise,
106    :path header field value must start with "/".  This function must
107    be called after ":method" header field was received.  This function
108    returns nonzero if path is valid.*/
check_path_flags(nghttp3_http_state * http)109 static int check_path_flags(nghttp3_http_state *http) {
110   return (http->flags & NGHTTP3_HTTP_FLAG_SCHEME_HTTP) == 0 ||
111          ((http->flags & NGHTTP3_HTTP_FLAG_PATH_REGULAR) ||
112           ((http->flags & NGHTTP3_HTTP_FLAG_METH_OPTIONS) &&
113            (http->flags & NGHTTP3_HTTP_FLAG_PATH_ASTERISK)));
114 }
115 
116 /* Generated by genchartbl.py */
117 static const int SF_KEY_CHARS[] = {
118     0 /* NUL  */, 0 /* SOH  */, 0 /* STX  */, 0 /* ETX  */, 0 /* EOT  */,
119     0 /* ENQ  */, 0 /* ACK  */, 0 /* BEL  */, 0 /* BS   */, 0 /* HT   */,
120     0 /* LF   */, 0 /* VT   */, 0 /* FF   */, 0 /* CR   */, 0 /* SO   */,
121     0 /* SI   */, 0 /* DLE  */, 0 /* DC1  */, 0 /* DC2  */, 0 /* DC3  */,
122     0 /* DC4  */, 0 /* NAK  */, 0 /* SYN  */, 0 /* ETB  */, 0 /* CAN  */,
123     0 /* EM   */, 0 /* SUB  */, 0 /* ESC  */, 0 /* FS   */, 0 /* GS   */,
124     0 /* RS   */, 0 /* US   */, 0 /* SPC  */, 0 /* !    */, 0 /* "    */,
125     0 /* #    */, 0 /* $    */, 0 /* %    */, 0 /* &    */, 0 /* '    */,
126     0 /* (    */, 0 /* )    */, 1 /* *    */, 0 /* +    */, 0 /* ,    */,
127     1 /* -    */, 1 /* .    */, 0 /* /    */, 1 /* 0    */, 1 /* 1    */,
128     1 /* 2    */, 1 /* 3    */, 1 /* 4    */, 1 /* 5    */, 1 /* 6    */,
129     1 /* 7    */, 1 /* 8    */, 1 /* 9    */, 0 /* :    */, 0 /* ;    */,
130     0 /* <    */, 0 /* =    */, 0 /* >    */, 0 /* ?    */, 0 /* @    */,
131     0 /* A    */, 0 /* B    */, 0 /* C    */, 0 /* D    */, 0 /* E    */,
132     0 /* F    */, 0 /* G    */, 0 /* H    */, 0 /* I    */, 0 /* J    */,
133     0 /* K    */, 0 /* L    */, 0 /* M    */, 0 /* N    */, 0 /* O    */,
134     0 /* P    */, 0 /* Q    */, 0 /* R    */, 0 /* S    */, 0 /* T    */,
135     0 /* U    */, 0 /* V    */, 0 /* W    */, 0 /* X    */, 0 /* Y    */,
136     0 /* Z    */, 0 /* [    */, 0 /* \    */, 0 /* ]    */, 0 /* ^    */,
137     1 /* _    */, 0 /* `    */, 1 /* a    */, 1 /* b    */, 1 /* c    */,
138     1 /* d    */, 1 /* e    */, 1 /* f    */, 1 /* g    */, 1 /* h    */,
139     1 /* i    */, 1 /* j    */, 1 /* k    */, 1 /* l    */, 1 /* m    */,
140     1 /* n    */, 1 /* o    */, 1 /* p    */, 1 /* q    */, 1 /* r    */,
141     1 /* s    */, 1 /* t    */, 1 /* u    */, 1 /* v    */, 1 /* w    */,
142     1 /* x    */, 1 /* y    */, 1 /* z    */, 0 /* {    */, 0 /* |    */,
143     0 /* }    */, 0 /* ~    */, 0 /* DEL  */, 0 /* 0x80 */, 0 /* 0x81 */,
144     0 /* 0x82 */, 0 /* 0x83 */, 0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */,
145     0 /* 0x87 */, 0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
146     0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */, 0 /* 0x90 */,
147     0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */, 0 /* 0x94 */, 0 /* 0x95 */,
148     0 /* 0x96 */, 0 /* 0x97 */, 0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */,
149     0 /* 0x9b */, 0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
150     0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */, 0 /* 0xa4 */,
151     0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */, 0 /* 0xa8 */, 0 /* 0xa9 */,
152     0 /* 0xaa */, 0 /* 0xab */, 0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */,
153     0 /* 0xaf */, 0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
154     0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */, 0 /* 0xb8 */,
155     0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */, 0 /* 0xbc */, 0 /* 0xbd */,
156     0 /* 0xbe */, 0 /* 0xbf */, 0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */,
157     0 /* 0xc3 */, 0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
158     0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */, 0 /* 0xcc */,
159     0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */, 0 /* 0xd0 */, 0 /* 0xd1 */,
160     0 /* 0xd2 */, 0 /* 0xd3 */, 0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */,
161     0 /* 0xd7 */, 0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
162     0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */, 0 /* 0xe0 */,
163     0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */, 0 /* 0xe4 */, 0 /* 0xe5 */,
164     0 /* 0xe6 */, 0 /* 0xe7 */, 0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */,
165     0 /* 0xeb */, 0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
166     0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */, 0 /* 0xf4 */,
167     0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */, 0 /* 0xf8 */, 0 /* 0xf9 */,
168     0 /* 0xfa */, 0 /* 0xfb */, 0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */,
169     0 /* 0xff */,
170 };
171 
sf_parse_key(const uint8_t * begin,const uint8_t * end)172 static nghttp3_ssize sf_parse_key(const uint8_t *begin, const uint8_t *end) {
173   const uint8_t *p = begin;
174 
175   if ((*p < 'a' || 'z' < *p) && *p != '*') {
176     return -1;
177   }
178 
179   for (; p != end && SF_KEY_CHARS[*p]; ++p)
180     ;
181 
182   return p - begin;
183 }
184 
sf_parse_integer_or_decimal(nghttp3_sf_value * dest,const uint8_t * begin,const uint8_t * end)185 static nghttp3_ssize sf_parse_integer_or_decimal(nghttp3_sf_value *dest,
186                                                  const uint8_t *begin,
187                                                  const uint8_t *end) {
188   const uint8_t *p = begin;
189   int sign = 1;
190   int64_t value = 0;
191   int type = NGHTTP3_SF_VALUE_TYPE_INTEGER;
192   size_t len = 0;
193   size_t fpos = 0;
194   size_t i;
195 
196   if (*p == '-') {
197     if (++p == end) {
198       return -1;
199     }
200 
201     sign = -1;
202   }
203 
204   if (*p < '0' || '9' < *p) {
205     return -1;
206   }
207 
208   for (; p != end; ++p) {
209     switch (*p) {
210     case '0':
211     case '1':
212     case '2':
213     case '3':
214     case '4':
215     case '5':
216     case '6':
217     case '7':
218     case '8':
219     case '9':
220       value *= 10;
221       value += *p - '0';
222 
223       if (++len > 15) {
224         return -1;
225       }
226 
227       break;
228     case '.':
229       if (type != NGHTTP3_SF_VALUE_TYPE_INTEGER) {
230         goto fin;
231       }
232 
233       if (len > 12) {
234         return -1;
235       }
236       fpos = len;
237       type = NGHTTP3_SF_VALUE_TYPE_DECIMAL;
238 
239       break;
240     default:
241       goto fin;
242     };
243   }
244 
245 fin:
246   switch (type) {
247   case NGHTTP3_SF_VALUE_TYPE_INTEGER:
248     if (dest) {
249       dest->type = (uint8_t)type;
250       dest->i = value * sign;
251     }
252 
253     return p - begin;
254   case NGHTTP3_SF_VALUE_TYPE_DECIMAL:
255     if (fpos == len || len - fpos > 3) {
256       return -1;
257     }
258 
259     if (dest) {
260       dest->type = (uint8_t)type;
261       dest->d = (double)value;
262       for (i = len - fpos; i > 0; --i) {
263         dest->d /= (double)10;
264       }
265       dest->d *= sign;
266     }
267 
268     return p - begin;
269   default:
270     assert(0);
271     abort();
272   }
273 }
274 
275 /* Generated by genchartbl.py */
276 static const int SF_DQUOTE_CHARS[] = {
277     0 /* NUL  */, 0 /* SOH  */, 0 /* STX  */, 0 /* ETX  */, 0 /* EOT  */,
278     0 /* ENQ  */, 0 /* ACK  */, 0 /* BEL  */, 0 /* BS   */, 0 /* HT   */,
279     0 /* LF   */, 0 /* VT   */, 0 /* FF   */, 0 /* CR   */, 0 /* SO   */,
280     0 /* SI   */, 0 /* DLE  */, 0 /* DC1  */, 0 /* DC2  */, 0 /* DC3  */,
281     0 /* DC4  */, 0 /* NAK  */, 0 /* SYN  */, 0 /* ETB  */, 0 /* CAN  */,
282     0 /* EM   */, 0 /* SUB  */, 0 /* ESC  */, 0 /* FS   */, 0 /* GS   */,
283     0 /* RS   */, 0 /* US   */, 1 /* SPC  */, 1 /* !    */, 0 /* "    */,
284     1 /* #    */, 1 /* $    */, 1 /* %    */, 1 /* &    */, 1 /* '    */,
285     1 /* (    */, 1 /* )    */, 1 /* *    */, 1 /* +    */, 1 /* ,    */,
286     1 /* -    */, 1 /* .    */, 1 /* /    */, 1 /* 0    */, 1 /* 1    */,
287     1 /* 2    */, 1 /* 3    */, 1 /* 4    */, 1 /* 5    */, 1 /* 6    */,
288     1 /* 7    */, 1 /* 8    */, 1 /* 9    */, 1 /* :    */, 1 /* ;    */,
289     1 /* <    */, 1 /* =    */, 1 /* >    */, 1 /* ?    */, 1 /* @    */,
290     1 /* A    */, 1 /* B    */, 1 /* C    */, 1 /* D    */, 1 /* E    */,
291     1 /* F    */, 1 /* G    */, 1 /* H    */, 1 /* I    */, 1 /* J    */,
292     1 /* K    */, 1 /* L    */, 1 /* M    */, 1 /* N    */, 1 /* O    */,
293     1 /* P    */, 1 /* Q    */, 1 /* R    */, 1 /* S    */, 1 /* T    */,
294     1 /* U    */, 1 /* V    */, 1 /* W    */, 1 /* X    */, 1 /* Y    */,
295     1 /* Z    */, 1 /* [    */, 0 /* \    */, 1 /* ]    */, 1 /* ^    */,
296     1 /* _    */, 1 /* `    */, 1 /* a    */, 1 /* b    */, 1 /* c    */,
297     1 /* d    */, 1 /* e    */, 1 /* f    */, 1 /* g    */, 1 /* h    */,
298     1 /* i    */, 1 /* j    */, 1 /* k    */, 1 /* l    */, 1 /* m    */,
299     1 /* n    */, 1 /* o    */, 1 /* p    */, 1 /* q    */, 1 /* r    */,
300     1 /* s    */, 1 /* t    */, 1 /* u    */, 1 /* v    */, 1 /* w    */,
301     1 /* x    */, 1 /* y    */, 1 /* z    */, 1 /* {    */, 1 /* |    */,
302     1 /* }    */, 1 /* ~    */, 0 /* DEL  */, 0 /* 0x80 */, 0 /* 0x81 */,
303     0 /* 0x82 */, 0 /* 0x83 */, 0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */,
304     0 /* 0x87 */, 0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
305     0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */, 0 /* 0x90 */,
306     0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */, 0 /* 0x94 */, 0 /* 0x95 */,
307     0 /* 0x96 */, 0 /* 0x97 */, 0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */,
308     0 /* 0x9b */, 0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
309     0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */, 0 /* 0xa4 */,
310     0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */, 0 /* 0xa8 */, 0 /* 0xa9 */,
311     0 /* 0xaa */, 0 /* 0xab */, 0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */,
312     0 /* 0xaf */, 0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
313     0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */, 0 /* 0xb8 */,
314     0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */, 0 /* 0xbc */, 0 /* 0xbd */,
315     0 /* 0xbe */, 0 /* 0xbf */, 0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */,
316     0 /* 0xc3 */, 0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
317     0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */, 0 /* 0xcc */,
318     0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */, 0 /* 0xd0 */, 0 /* 0xd1 */,
319     0 /* 0xd2 */, 0 /* 0xd3 */, 0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */,
320     0 /* 0xd7 */, 0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
321     0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */, 0 /* 0xe0 */,
322     0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */, 0 /* 0xe4 */, 0 /* 0xe5 */,
323     0 /* 0xe6 */, 0 /* 0xe7 */, 0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */,
324     0 /* 0xeb */, 0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
325     0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */, 0 /* 0xf4 */,
326     0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */, 0 /* 0xf8 */, 0 /* 0xf9 */,
327     0 /* 0xfa */, 0 /* 0xfb */, 0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */,
328     0 /* 0xff */,
329 };
330 
sf_parse_string(nghttp3_sf_value * dest,const uint8_t * begin,const uint8_t * end)331 static nghttp3_ssize sf_parse_string(nghttp3_sf_value *dest,
332                                      const uint8_t *begin, const uint8_t *end) {
333   const uint8_t *p = begin;
334 
335   if (*p++ != '"') {
336     return -1;
337   }
338 
339   for (; p != end; ++p) {
340     switch (*p) {
341     case '\\':
342       if (++p == end) {
343         return -1;
344       }
345 
346       switch (*p) {
347       case '"':
348       case '\\':
349         break;
350       default:
351         return -1;
352       }
353 
354       break;
355     case '"':
356       if (dest) {
357         dest->type = NGHTTP3_SF_VALUE_TYPE_STRING;
358         dest->s.base = begin + 1;
359         dest->s.len = (size_t)(p - dest->s.base);
360       }
361 
362       ++p;
363 
364       return p - begin;
365     default:
366       if (!SF_DQUOTE_CHARS[*p]) {
367         return -1;
368       }
369     }
370   }
371 
372   return -1;
373 }
374 
375 /* Generated by genchartbl.py */
376 static const int SF_TOKEN_CHARS[] = {
377     0 /* NUL  */, 0 /* SOH  */, 0 /* STX  */, 0 /* ETX  */, 0 /* EOT  */,
378     0 /* ENQ  */, 0 /* ACK  */, 0 /* BEL  */, 0 /* BS   */, 0 /* HT   */,
379     0 /* LF   */, 0 /* VT   */, 0 /* FF   */, 0 /* CR   */, 0 /* SO   */,
380     0 /* SI   */, 0 /* DLE  */, 0 /* DC1  */, 0 /* DC2  */, 0 /* DC3  */,
381     0 /* DC4  */, 0 /* NAK  */, 0 /* SYN  */, 0 /* ETB  */, 0 /* CAN  */,
382     0 /* EM   */, 0 /* SUB  */, 0 /* ESC  */, 0 /* FS   */, 0 /* GS   */,
383     0 /* RS   */, 0 /* US   */, 0 /* SPC  */, 1 /* !    */, 0 /* "    */,
384     1 /* #    */, 1 /* $    */, 1 /* %    */, 1 /* &    */, 1 /* '    */,
385     0 /* (    */, 0 /* )    */, 1 /* *    */, 1 /* +    */, 0 /* ,    */,
386     1 /* -    */, 1 /* .    */, 1 /* /    */, 1 /* 0    */, 1 /* 1    */,
387     1 /* 2    */, 1 /* 3    */, 1 /* 4    */, 1 /* 5    */, 1 /* 6    */,
388     1 /* 7    */, 1 /* 8    */, 1 /* 9    */, 1 /* :    */, 0 /* ;    */,
389     0 /* <    */, 0 /* =    */, 0 /* >    */, 0 /* ?    */, 0 /* @    */,
390     1 /* A    */, 1 /* B    */, 1 /* C    */, 1 /* D    */, 1 /* E    */,
391     1 /* F    */, 1 /* G    */, 1 /* H    */, 1 /* I    */, 1 /* J    */,
392     1 /* K    */, 1 /* L    */, 1 /* M    */, 1 /* N    */, 1 /* O    */,
393     1 /* P    */, 1 /* Q    */, 1 /* R    */, 1 /* S    */, 1 /* T    */,
394     1 /* U    */, 1 /* V    */, 1 /* W    */, 1 /* X    */, 1 /* Y    */,
395     1 /* Z    */, 0 /* [    */, 0 /* \    */, 0 /* ]    */, 1 /* ^    */,
396     1 /* _    */, 1 /* `    */, 1 /* a    */, 1 /* b    */, 1 /* c    */,
397     1 /* d    */, 1 /* e    */, 1 /* f    */, 1 /* g    */, 1 /* h    */,
398     1 /* i    */, 1 /* j    */, 1 /* k    */, 1 /* l    */, 1 /* m    */,
399     1 /* n    */, 1 /* o    */, 1 /* p    */, 1 /* q    */, 1 /* r    */,
400     1 /* s    */, 1 /* t    */, 1 /* u    */, 1 /* v    */, 1 /* w    */,
401     1 /* x    */, 1 /* y    */, 1 /* z    */, 0 /* {    */, 1 /* |    */,
402     0 /* }    */, 1 /* ~    */, 0 /* DEL  */, 0 /* 0x80 */, 0 /* 0x81 */,
403     0 /* 0x82 */, 0 /* 0x83 */, 0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */,
404     0 /* 0x87 */, 0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
405     0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */, 0 /* 0x90 */,
406     0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */, 0 /* 0x94 */, 0 /* 0x95 */,
407     0 /* 0x96 */, 0 /* 0x97 */, 0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */,
408     0 /* 0x9b */, 0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
409     0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */, 0 /* 0xa4 */,
410     0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */, 0 /* 0xa8 */, 0 /* 0xa9 */,
411     0 /* 0xaa */, 0 /* 0xab */, 0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */,
412     0 /* 0xaf */, 0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
413     0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */, 0 /* 0xb8 */,
414     0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */, 0 /* 0xbc */, 0 /* 0xbd */,
415     0 /* 0xbe */, 0 /* 0xbf */, 0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */,
416     0 /* 0xc3 */, 0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
417     0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */, 0 /* 0xcc */,
418     0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */, 0 /* 0xd0 */, 0 /* 0xd1 */,
419     0 /* 0xd2 */, 0 /* 0xd3 */, 0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */,
420     0 /* 0xd7 */, 0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
421     0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */, 0 /* 0xe0 */,
422     0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */, 0 /* 0xe4 */, 0 /* 0xe5 */,
423     0 /* 0xe6 */, 0 /* 0xe7 */, 0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */,
424     0 /* 0xeb */, 0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
425     0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */, 0 /* 0xf4 */,
426     0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */, 0 /* 0xf8 */, 0 /* 0xf9 */,
427     0 /* 0xfa */, 0 /* 0xfb */, 0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */,
428     0 /* 0xff */,
429 };
430 
sf_parse_token(nghttp3_sf_value * dest,const uint8_t * begin,const uint8_t * end)431 static nghttp3_ssize sf_parse_token(nghttp3_sf_value *dest,
432                                     const uint8_t *begin, const uint8_t *end) {
433   const uint8_t *p = begin;
434 
435   if ((*p < 'A' || 'Z' < *p) && (*p < 'a' || 'z' < *p) && *p != '*') {
436     return -1;
437   }
438 
439   for (; p != end && SF_TOKEN_CHARS[*p]; ++p)
440     ;
441 
442   if (dest) {
443     dest->type = NGHTTP3_SF_VALUE_TYPE_TOKEN;
444     dest->s.base = begin;
445     dest->s.len = (size_t)(p - begin);
446   }
447 
448   return p - begin;
449 }
450 
451 /* Generated by genchartbl.py */
452 static const int SF_BYTESEQ_CHARS[] = {
453     0 /* NUL  */, 0 /* SOH  */, 0 /* STX  */, 0 /* ETX  */, 0 /* EOT  */,
454     0 /* ENQ  */, 0 /* ACK  */, 0 /* BEL  */, 0 /* BS   */, 0 /* HT   */,
455     0 /* LF   */, 0 /* VT   */, 0 /* FF   */, 0 /* CR   */, 0 /* SO   */,
456     0 /* SI   */, 0 /* DLE  */, 0 /* DC1  */, 0 /* DC2  */, 0 /* DC3  */,
457     0 /* DC4  */, 0 /* NAK  */, 0 /* SYN  */, 0 /* ETB  */, 0 /* CAN  */,
458     0 /* EM   */, 0 /* SUB  */, 0 /* ESC  */, 0 /* FS   */, 0 /* GS   */,
459     0 /* RS   */, 0 /* US   */, 0 /* SPC  */, 0 /* !    */, 0 /* "    */,
460     0 /* #    */, 0 /* $    */, 0 /* %    */, 0 /* &    */, 0 /* '    */,
461     0 /* (    */, 0 /* )    */, 0 /* *    */, 1 /* +    */, 0 /* ,    */,
462     0 /* -    */, 0 /* .    */, 1 /* /    */, 1 /* 0    */, 1 /* 1    */,
463     1 /* 2    */, 1 /* 3    */, 1 /* 4    */, 1 /* 5    */, 1 /* 6    */,
464     1 /* 7    */, 1 /* 8    */, 1 /* 9    */, 0 /* :    */, 0 /* ;    */,
465     0 /* <    */, 1 /* =    */, 0 /* >    */, 0 /* ?    */, 0 /* @    */,
466     1 /* A    */, 1 /* B    */, 1 /* C    */, 1 /* D    */, 1 /* E    */,
467     1 /* F    */, 1 /* G    */, 1 /* H    */, 1 /* I    */, 1 /* J    */,
468     1 /* K    */, 1 /* L    */, 1 /* M    */, 1 /* N    */, 1 /* O    */,
469     1 /* P    */, 1 /* Q    */, 1 /* R    */, 1 /* S    */, 1 /* T    */,
470     1 /* U    */, 1 /* V    */, 1 /* W    */, 1 /* X    */, 1 /* Y    */,
471     1 /* Z    */, 0 /* [    */, 0 /* \    */, 0 /* ]    */, 0 /* ^    */,
472     0 /* _    */, 0 /* `    */, 1 /* a    */, 1 /* b    */, 1 /* c    */,
473     1 /* d    */, 1 /* e    */, 1 /* f    */, 1 /* g    */, 1 /* h    */,
474     1 /* i    */, 1 /* j    */, 1 /* k    */, 1 /* l    */, 1 /* m    */,
475     1 /* n    */, 1 /* o    */, 1 /* p    */, 1 /* q    */, 1 /* r    */,
476     1 /* s    */, 1 /* t    */, 1 /* u    */, 1 /* v    */, 1 /* w    */,
477     1 /* x    */, 1 /* y    */, 1 /* z    */, 0 /* {    */, 0 /* |    */,
478     0 /* }    */, 0 /* ~    */, 0 /* DEL  */, 0 /* 0x80 */, 0 /* 0x81 */,
479     0 /* 0x82 */, 0 /* 0x83 */, 0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */,
480     0 /* 0x87 */, 0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
481     0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */, 0 /* 0x90 */,
482     0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */, 0 /* 0x94 */, 0 /* 0x95 */,
483     0 /* 0x96 */, 0 /* 0x97 */, 0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */,
484     0 /* 0x9b */, 0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
485     0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */, 0 /* 0xa4 */,
486     0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */, 0 /* 0xa8 */, 0 /* 0xa9 */,
487     0 /* 0xaa */, 0 /* 0xab */, 0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */,
488     0 /* 0xaf */, 0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
489     0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */, 0 /* 0xb8 */,
490     0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */, 0 /* 0xbc */, 0 /* 0xbd */,
491     0 /* 0xbe */, 0 /* 0xbf */, 0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */,
492     0 /* 0xc3 */, 0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
493     0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */, 0 /* 0xcc */,
494     0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */, 0 /* 0xd0 */, 0 /* 0xd1 */,
495     0 /* 0xd2 */, 0 /* 0xd3 */, 0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */,
496     0 /* 0xd7 */, 0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
497     0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */, 0 /* 0xe0 */,
498     0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */, 0 /* 0xe4 */, 0 /* 0xe5 */,
499     0 /* 0xe6 */, 0 /* 0xe7 */, 0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */,
500     0 /* 0xeb */, 0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
501     0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */, 0 /* 0xf4 */,
502     0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */, 0 /* 0xf8 */, 0 /* 0xf9 */,
503     0 /* 0xfa */, 0 /* 0xfb */, 0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */,
504     0 /* 0xff */,
505 };
506 
sf_parse_byteseq(nghttp3_sf_value * dest,const uint8_t * begin,const uint8_t * end)507 static nghttp3_ssize sf_parse_byteseq(nghttp3_sf_value *dest,
508                                       const uint8_t *begin,
509                                       const uint8_t *end) {
510   const uint8_t *p = begin;
511 
512   if (*p++ != ':') {
513     return -1;
514   }
515 
516   for (; p != end; ++p) {
517     switch (*p) {
518     case ':':
519       if (dest) {
520         dest->type = NGHTTP3_SF_VALUE_TYPE_BYTESEQ;
521         dest->s.base = begin + 1;
522         dest->s.len = (size_t)(p - dest->s.base);
523       }
524 
525       ++p;
526 
527       return p - begin;
528     default:
529       if (!SF_BYTESEQ_CHARS[*p]) {
530         return -1;
531       }
532     }
533   }
534 
535   return -1;
536 }
537 
sf_parse_boolean(nghttp3_sf_value * dest,const uint8_t * begin,const uint8_t * end)538 static nghttp3_ssize sf_parse_boolean(nghttp3_sf_value *dest,
539                                       const uint8_t *begin,
540                                       const uint8_t *end) {
541   const uint8_t *p = begin;
542   int b;
543 
544   if (*p++ != '?') {
545     return -1;
546   }
547 
548   if (p == end) {
549     return -1;
550   }
551 
552   switch (*p++) {
553   case '0':
554     b = 0;
555     break;
556   case '1':
557     b = 1;
558     break;
559   default:
560     return -1;
561   }
562 
563   if (dest) {
564     dest->type = NGHTTP3_SF_VALUE_TYPE_BOOLEAN;
565     dest->b = b;
566   }
567 
568   return p - begin;
569 }
570 
sf_parse_bare_item(nghttp3_sf_value * dest,const uint8_t * begin,const uint8_t * end)571 static nghttp3_ssize sf_parse_bare_item(nghttp3_sf_value *dest,
572                                         const uint8_t *begin,
573                                         const uint8_t *end) {
574   switch (*begin) {
575   case '-':
576   case '0':
577   case '1':
578   case '2':
579   case '3':
580   case '4':
581   case '5':
582   case '6':
583   case '7':
584   case '8':
585   case '9':
586     return sf_parse_integer_or_decimal(dest, begin, end);
587   case '"':
588     return sf_parse_string(dest, begin, end);
589   case '*':
590     return sf_parse_token(dest, begin, end);
591   case ':':
592     return sf_parse_byteseq(dest, begin, end);
593   case '?':
594     return sf_parse_boolean(dest, begin, end);
595   default:
596     if (('A' <= *begin && *begin <= 'Z') || ('a' <= *begin && *begin <= 'z')) {
597       return sf_parse_token(dest, begin, end);
598     }
599     return -1;
600   }
601 }
602 
603 #define sf_discard_sp_end_err(BEGIN, END, ERR)                                 \
604   for (;; ++(BEGIN)) {                                                         \
605     if ((BEGIN) == (END)) {                                                    \
606       return (ERR);                                                            \
607     }                                                                          \
608     if (*(BEGIN) != ' ') {                                                     \
609       break;                                                                   \
610     }                                                                          \
611   }
612 
sf_parse_params(const uint8_t * begin,const uint8_t * end)613 static nghttp3_ssize sf_parse_params(const uint8_t *begin, const uint8_t *end) {
614   const uint8_t *p = begin;
615   nghttp3_ssize slen;
616 
617   for (; p != end && *p == ';';) {
618     ++p;
619 
620     sf_discard_sp_end_err(p, end, -1);
621 
622     slen = sf_parse_key(p, end);
623     if (slen < 0) {
624       return -1;
625     }
626 
627     p += slen;
628 
629     if (p == end || *p != '=') {
630       /* Boolean true */
631     } else if (++p == end) {
632       return -1;
633     } else {
634       slen = sf_parse_bare_item(NULL, p, end);
635       if (slen < 0) {
636         return -1;
637       }
638 
639       p += slen;
640     }
641   }
642 
643   return p - begin;
644 }
645 
sf_parse_item(nghttp3_sf_value * dest,const uint8_t * begin,const uint8_t * end)646 static nghttp3_ssize sf_parse_item(nghttp3_sf_value *dest, const uint8_t *begin,
647                                    const uint8_t *end) {
648   const uint8_t *p = begin;
649   nghttp3_ssize slen;
650 
651   slen = sf_parse_bare_item(dest, p, end);
652   if (slen < 0) {
653     return -1;
654   }
655 
656   p += slen;
657 
658   slen = sf_parse_params(p, end);
659   if (slen < 0) {
660     return -1;
661   }
662 
663   p += slen;
664 
665   return p - begin;
666 }
667 
nghttp3_sf_parse_item(nghttp3_sf_value * dest,const uint8_t * begin,const uint8_t * end)668 nghttp3_ssize nghttp3_sf_parse_item(nghttp3_sf_value *dest,
669                                     const uint8_t *begin, const uint8_t *end) {
670   return sf_parse_item(dest, begin, end);
671 }
672 
sf_parse_inner_list(nghttp3_sf_value * dest,const uint8_t * begin,const uint8_t * end)673 static nghttp3_ssize sf_parse_inner_list(nghttp3_sf_value *dest,
674                                          const uint8_t *begin,
675                                          const uint8_t *end) {
676   const uint8_t *p = begin;
677   nghttp3_ssize slen;
678 
679   if (*p++ != '(') {
680     return -1;
681   }
682 
683   for (;;) {
684     sf_discard_sp_end_err(p, end, -1);
685 
686     if (*p == ')') {
687       ++p;
688 
689       slen = sf_parse_params(p, end);
690       if (slen < 0) {
691         return -1;
692       }
693 
694       p += slen;
695 
696       if (dest) {
697         dest->type = NGHTTP3_SF_VALUE_TYPE_INNER_LIST;
698       }
699 
700       return p - begin;
701     }
702 
703     slen = sf_parse_item(NULL, p, end);
704     if (slen < 0) {
705       return -1;
706     }
707 
708     p += slen;
709 
710     if (p == end || (*p != ' ' && *p != ')')) {
711       return -1;
712     }
713   }
714 }
715 
nghttp3_sf_parse_inner_list(nghttp3_sf_value * dest,const uint8_t * begin,const uint8_t * end)716 nghttp3_ssize nghttp3_sf_parse_inner_list(nghttp3_sf_value *dest,
717                                           const uint8_t *begin,
718                                           const uint8_t *end) {
719   return sf_parse_inner_list(dest, begin, end);
720 }
721 
sf_parse_item_or_inner_list(nghttp3_sf_value * dest,const uint8_t * begin,const uint8_t * end)722 static nghttp3_ssize sf_parse_item_or_inner_list(nghttp3_sf_value *dest,
723                                                  const uint8_t *begin,
724                                                  const uint8_t *end) {
725   if (*begin == '(') {
726     return sf_parse_inner_list(dest, begin, end);
727   }
728 
729   return sf_parse_item(dest, begin, end);
730 }
731 
732 #define sf_discard_ows(BEGIN, END)                                             \
733   for (;; ++(BEGIN)) {                                                         \
734     if ((BEGIN) == (END)) {                                                    \
735       goto fin;                                                                \
736     }                                                                          \
737     if (*(BEGIN) != ' ' && *(BEGIN) != '\t') {                                 \
738       break;                                                                   \
739     }                                                                          \
740   }
741 
742 #define sf_discard_ows_end_err(BEGIN, END, ERR)                                \
743   for (;; ++(BEGIN)) {                                                         \
744     if ((BEGIN) == (END)) {                                                    \
745       return (ERR);                                                            \
746     }                                                                          \
747     if (*(BEGIN) != ' ' && *(BEGIN) != '\t') {                                 \
748       break;                                                                   \
749     }                                                                          \
750   }
751 
nghttp3_http_parse_priority(nghttp3_pri * dest,const uint8_t * value,size_t valuelen)752 int nghttp3_http_parse_priority(nghttp3_pri *dest, const uint8_t *value,
753                                 size_t valuelen) {
754   const uint8_t *p = value, *end = value + valuelen;
755   nghttp3_ssize slen;
756   nghttp3_sf_value val;
757   nghttp3_pri pri = *dest;
758   const uint8_t *key;
759   size_t keylen;
760 
761   for (; p != end && *p == ' '; ++p)
762     ;
763 
764   for (; p != end;) {
765     slen = sf_parse_key(p, end);
766     if (slen < 0) {
767       return NGHTTP3_ERR_INVALID_ARGUMENT;
768     }
769 
770     key = p;
771     keylen = (size_t)slen;
772 
773     p += slen;
774 
775     if (p == end || *p != '=') {
776       /* Boolean true */
777       val.type = NGHTTP3_SF_VALUE_TYPE_BOOLEAN;
778       val.b = 1;
779 
780       slen = sf_parse_params(p, end);
781       if (slen < 0) {
782         return NGHTTP3_ERR_INVALID_ARGUMENT;
783       }
784     } else if (++p == end) {
785       return NGHTTP3_ERR_INVALID_ARGUMENT;
786     } else {
787       slen = sf_parse_item_or_inner_list(&val, p, end);
788       if (slen < 0) {
789         return NGHTTP3_ERR_INVALID_ARGUMENT;
790       }
791     }
792 
793     p += slen;
794 
795     if (keylen == 1) {
796       switch (key[0]) {
797       case 'i':
798         if (val.type != NGHTTP3_SF_VALUE_TYPE_BOOLEAN) {
799           return NGHTTP3_ERR_INVALID_ARGUMENT;
800         }
801 
802         pri.inc = val.b;
803 
804         break;
805       case 'u':
806         if (val.type != NGHTTP3_SF_VALUE_TYPE_INTEGER ||
807             val.i < NGHTTP3_URGENCY_HIGH || NGHTTP3_URGENCY_LOW < val.i) {
808           return NGHTTP3_ERR_INVALID_ARGUMENT;
809         }
810 
811         pri.urgency = (uint32_t)val.i;
812 
813         break;
814       }
815     }
816 
817     sf_discard_ows(p, end);
818 
819     if (*p++ != ',') {
820       return NGHTTP3_ERR_INVALID_ARGUMENT;
821     }
822 
823     sf_discard_ows_end_err(p, end, NGHTTP3_ERR_INVALID_ARGUMENT);
824   }
825 
826 fin:
827   *dest = pri;
828 
829   return 0;
830 }
831 
http_request_on_header(nghttp3_http_state * http,nghttp3_qpack_nv * nv,int trailers,int connect_protocol)832 static int http_request_on_header(nghttp3_http_state *http,
833                                   nghttp3_qpack_nv *nv, int trailers,
834                                   int connect_protocol) {
835   nghttp3_pri pri;
836 
837   if (nv->name->base[0] == ':') {
838     if (trailers ||
839         (http->flags & NGHTTP3_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED)) {
840       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
841     }
842   }
843 
844   switch (nv->token) {
845   case NGHTTP3_QPACK_TOKEN__AUTHORITY:
846     if (!check_pseudo_header(http, nv, NGHTTP3_HTTP_FLAG__AUTHORITY)) {
847       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
848     }
849     break;
850   case NGHTTP3_QPACK_TOKEN__METHOD:
851     if (!check_pseudo_header(http, nv, NGHTTP3_HTTP_FLAG__METHOD)) {
852       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
853     }
854     switch (nv->value->len) {
855     case 4:
856       if (lstreq("HEAD", nv->value->base, nv->value->len)) {
857         http->flags |= NGHTTP3_HTTP_FLAG_METH_HEAD;
858       }
859       break;
860     case 7:
861       switch (nv->value->base[6]) {
862       case 'T':
863         if (lstreq("CONNECT", nv->value->base, nv->value->len)) {
864           http->flags |= NGHTTP3_HTTP_FLAG_METH_CONNECT;
865         }
866         break;
867       case 'S':
868         if (lstreq("OPTIONS", nv->value->base, nv->value->len)) {
869           http->flags |= NGHTTP3_HTTP_FLAG_METH_OPTIONS;
870         }
871         break;
872       }
873       break;
874     }
875     break;
876   case NGHTTP3_QPACK_TOKEN__PATH:
877     if (!check_pseudo_header(http, nv, NGHTTP3_HTTP_FLAG__PATH)) {
878       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
879     }
880     if (nv->value->base[0] == '/') {
881       http->flags |= NGHTTP3_HTTP_FLAG_PATH_REGULAR;
882     } else if (nv->value->len == 1 && nv->value->base[0] == '*') {
883       http->flags |= NGHTTP3_HTTP_FLAG_PATH_ASTERISK;
884     }
885     break;
886   case NGHTTP3_QPACK_TOKEN__SCHEME:
887     if (!check_pseudo_header(http, nv, NGHTTP3_HTTP_FLAG__SCHEME)) {
888       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
889     }
890     if ((nv->value->len == 4 && memieq("http", nv->value->base, 4)) ||
891         (nv->value->len == 5 && memieq("https", nv->value->base, 5))) {
892       http->flags |= NGHTTP3_HTTP_FLAG_SCHEME_HTTP;
893     }
894     break;
895   case NGHTTP3_QPACK_TOKEN__PROTOCOL:
896     if (!connect_protocol) {
897       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
898     }
899 
900     if (!check_pseudo_header(http, nv, NGHTTP3_HTTP_FLAG__PROTOCOL)) {
901       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
902     }
903     break;
904   case NGHTTP3_QPACK_TOKEN_HOST:
905     if (!check_pseudo_header(http, nv, NGHTTP3_HTTP_FLAG_HOST)) {
906       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
907     }
908     break;
909   case NGHTTP3_QPACK_TOKEN_CONTENT_LENGTH: {
910     /* https://tools.ietf.org/html/rfc7230#section-4.1.2: A sender
911        MUST NOT generate a trailer that contains a field necessary for
912        message framing (e.g., Transfer-Encoding and Content-Length),
913        ... */
914     if (trailers) {
915       return NGHTTP3_ERR_REMOVE_HTTP_HEADER;
916     }
917     if (http->content_length != -1) {
918       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
919     }
920     http->content_length = parse_uint(nv->value->base, nv->value->len);
921     if (http->content_length == -1) {
922       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
923     }
924     break;
925   }
926   /* disallowed header fields */
927   case NGHTTP3_QPACK_TOKEN_CONNECTION:
928   case NGHTTP3_QPACK_TOKEN_KEEP_ALIVE:
929   case NGHTTP3_QPACK_TOKEN_PROXY_CONNECTION:
930   case NGHTTP3_QPACK_TOKEN_TRANSFER_ENCODING:
931   case NGHTTP3_QPACK_TOKEN_UPGRADE:
932     return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
933   case NGHTTP3_QPACK_TOKEN_TE:
934     if (!lstrieq("trailers", nv->value->base, nv->value->len)) {
935       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
936     }
937     break;
938   case NGHTTP3_QPACK_TOKEN_PRIORITY:
939     pri.urgency = nghttp3_pri_uint8_urgency(http->pri);
940     pri.inc = nghttp3_pri_uint8_inc(http->pri);
941     if (nghttp3_http_parse_priority(&pri, nv->value->base, nv->value->len) ==
942         0) {
943       http->pri = nghttp3_pri_to_uint8(&pri);
944     }
945     break;
946   default:
947     if (nv->name->base[0] == ':') {
948       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
949     }
950   }
951 
952   return 0;
953 }
954 
http_response_on_header(nghttp3_http_state * http,nghttp3_qpack_nv * nv,int trailers)955 static int http_response_on_header(nghttp3_http_state *http,
956                                    nghttp3_qpack_nv *nv, int trailers) {
957   if (nv->name->base[0] == ':') {
958     if (trailers ||
959         (http->flags & NGHTTP3_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED)) {
960       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
961     }
962   }
963 
964   switch (nv->token) {
965   case NGHTTP3_QPACK_TOKEN__STATUS: {
966     if (!check_pseudo_header(http, nv, NGHTTP3_HTTP_FLAG__STATUS)) {
967       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
968     }
969     if (nv->value->len != 3) {
970       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
971     }
972     http->status_code = (int16_t)parse_uint(nv->value->base, nv->value->len);
973     if (http->status_code < 100 || http->status_code == 101) {
974       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
975     }
976     break;
977   }
978   case NGHTTP3_QPACK_TOKEN_CONTENT_LENGTH: {
979     /* https://tools.ietf.org/html/rfc7230#section-4.1.2: A sender
980        MUST NOT generate a trailer that contains a field necessary for
981        message framing (e.g., Transfer-Encoding and Content-Length),
982        ... */
983     if (trailers) {
984       return NGHTTP3_ERR_REMOVE_HTTP_HEADER;
985     }
986     if (http->status_code == 204) {
987       /* content-length header field in 204 response is prohibited by
988          RFC 7230.  But some widely used servers send content-length:
989          0.  Until they get fixed, we ignore it. */
990       if (http->content_length != -1) {
991         /* Found multiple content-length field */
992         return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
993       }
994       if (!lstrieq("0", nv->value->base, nv->value->len)) {
995         return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
996       }
997       http->content_length = 0;
998       return NGHTTP3_ERR_REMOVE_HTTP_HEADER;
999     }
1000     if (http->status_code / 100 == 1) {
1001       return NGHTTP3_ERR_REMOVE_HTTP_HEADER;
1002     }
1003     /* https://tools.ietf.org/html/rfc7230#section-3.3.3 */
1004     if (http->status_code / 100 == 2 &&
1005         (http->flags & NGHTTP3_HTTP_FLAG_METH_CONNECT)) {
1006       return NGHTTP3_ERR_REMOVE_HTTP_HEADER;
1007     }
1008     if (http->content_length != -1) {
1009       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
1010     }
1011     http->content_length = parse_uint(nv->value->base, nv->value->len);
1012     if (http->content_length == -1) {
1013       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
1014     }
1015     break;
1016   }
1017   /* disallowed header fields */
1018   case NGHTTP3_QPACK_TOKEN_CONNECTION:
1019   case NGHTTP3_QPACK_TOKEN_KEEP_ALIVE:
1020   case NGHTTP3_QPACK_TOKEN_PROXY_CONNECTION:
1021   case NGHTTP3_QPACK_TOKEN_TRANSFER_ENCODING:
1022   case NGHTTP3_QPACK_TOKEN_UPGRADE:
1023     return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
1024   case NGHTTP3_QPACK_TOKEN_TE:
1025     if (!lstrieq("trailers", nv->value->base, nv->value->len)) {
1026       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
1027     }
1028     break;
1029   default:
1030     if (nv->name->base[0] == ':') {
1031       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
1032     }
1033   }
1034 
1035   return 0;
1036 }
1037 
1038 /* Generated by genauthroitychartbl.py */
1039 static char VALID_AUTHORITY_CHARS[] = {
1040     0 /* NUL  */, 0 /* SOH  */, 0 /* STX  */, 0 /* ETX  */,
1041     0 /* EOT  */, 0 /* ENQ  */, 0 /* ACK  */, 0 /* BEL  */,
1042     0 /* BS   */, 0 /* HT   */, 0 /* LF   */, 0 /* VT   */,
1043     0 /* FF   */, 0 /* CR   */, 0 /* SO   */, 0 /* SI   */,
1044     0 /* DLE  */, 0 /* DC1  */, 0 /* DC2  */, 0 /* DC3  */,
1045     0 /* DC4  */, 0 /* NAK  */, 0 /* SYN  */, 0 /* ETB  */,
1046     0 /* CAN  */, 0 /* EM   */, 0 /* SUB  */, 0 /* ESC  */,
1047     0 /* FS   */, 0 /* GS   */, 0 /* RS   */, 0 /* US   */,
1048     0 /* SPC  */, 1 /* !    */, 0 /* "    */, 0 /* #    */,
1049     1 /* $    */, 1 /* %    */, 1 /* &    */, 1 /* '    */,
1050     1 /* (    */, 1 /* )    */, 1 /* *    */, 1 /* +    */,
1051     1 /* ,    */, 1 /* -    */, 1 /* .    */, 0 /* /    */,
1052     1 /* 0    */, 1 /* 1    */, 1 /* 2    */, 1 /* 3    */,
1053     1 /* 4    */, 1 /* 5    */, 1 /* 6    */, 1 /* 7    */,
1054     1 /* 8    */, 1 /* 9    */, 1 /* :    */, 1 /* ;    */,
1055     0 /* <    */, 1 /* =    */, 0 /* >    */, 0 /* ?    */,
1056     1 /* @    */, 1 /* A    */, 1 /* B    */, 1 /* C    */,
1057     1 /* D    */, 1 /* E    */, 1 /* F    */, 1 /* G    */,
1058     1 /* H    */, 1 /* I    */, 1 /* J    */, 1 /* K    */,
1059     1 /* L    */, 1 /* M    */, 1 /* N    */, 1 /* O    */,
1060     1 /* P    */, 1 /* Q    */, 1 /* R    */, 1 /* S    */,
1061     1 /* T    */, 1 /* U    */, 1 /* V    */, 1 /* W    */,
1062     1 /* X    */, 1 /* Y    */, 1 /* Z    */, 1 /* [    */,
1063     0 /* \    */, 1 /* ]    */, 0 /* ^    */, 1 /* _    */,
1064     0 /* `    */, 1 /* a    */, 1 /* b    */, 1 /* c    */,
1065     1 /* d    */, 1 /* e    */, 1 /* f    */, 1 /* g    */,
1066     1 /* h    */, 1 /* i    */, 1 /* j    */, 1 /* k    */,
1067     1 /* l    */, 1 /* m    */, 1 /* n    */, 1 /* o    */,
1068     1 /* p    */, 1 /* q    */, 1 /* r    */, 1 /* s    */,
1069     1 /* t    */, 1 /* u    */, 1 /* v    */, 1 /* w    */,
1070     1 /* x    */, 1 /* y    */, 1 /* z    */, 0 /* {    */,
1071     0 /* |    */, 0 /* }    */, 1 /* ~    */, 0 /* DEL  */,
1072     0 /* 0x80 */, 0 /* 0x81 */, 0 /* 0x82 */, 0 /* 0x83 */,
1073     0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, 0 /* 0x87 */,
1074     0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
1075     0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */,
1076     0 /* 0x90 */, 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */,
1077     0 /* 0x94 */, 0 /* 0x95 */, 0 /* 0x96 */, 0 /* 0x97 */,
1078     0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, 0 /* 0x9b */,
1079     0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
1080     0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */,
1081     0 /* 0xa4 */, 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */,
1082     0 /* 0xa8 */, 0 /* 0xa9 */, 0 /* 0xaa */, 0 /* 0xab */,
1083     0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, 0 /* 0xaf */,
1084     0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
1085     0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */,
1086     0 /* 0xb8 */, 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */,
1087     0 /* 0xbc */, 0 /* 0xbd */, 0 /* 0xbe */, 0 /* 0xbf */,
1088     0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, 0 /* 0xc3 */,
1089     0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
1090     0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */,
1091     0 /* 0xcc */, 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */,
1092     0 /* 0xd0 */, 0 /* 0xd1 */, 0 /* 0xd2 */, 0 /* 0xd3 */,
1093     0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, 0 /* 0xd7 */,
1094     0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
1095     0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */,
1096     0 /* 0xe0 */, 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */,
1097     0 /* 0xe4 */, 0 /* 0xe5 */, 0 /* 0xe6 */, 0 /* 0xe7 */,
1098     0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, 0 /* 0xeb */,
1099     0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
1100     0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */,
1101     0 /* 0xf4 */, 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */,
1102     0 /* 0xf8 */, 0 /* 0xf9 */, 0 /* 0xfa */, 0 /* 0xfb */,
1103     0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, 0 /* 0xff */
1104 };
1105 
check_authority(const uint8_t * value,size_t len)1106 static int check_authority(const uint8_t *value, size_t len) {
1107   const uint8_t *last;
1108   for (last = value + len; value != last; ++value) {
1109     if (!VALID_AUTHORITY_CHARS[*value]) {
1110       return 0;
1111     }
1112   }
1113   return 1;
1114 }
1115 
check_scheme(const uint8_t * value,size_t len)1116 static int check_scheme(const uint8_t *value, size_t len) {
1117   const uint8_t *last;
1118   if (len == 0) {
1119     return 0;
1120   }
1121 
1122   if (!(('A' <= *value && *value <= 'Z') || ('a' <= *value && *value <= 'z'))) {
1123     return 0;
1124   }
1125 
1126   last = value + len;
1127   ++value;
1128 
1129   for (; value != last; ++value) {
1130     if (!(('A' <= *value && *value <= 'Z') ||
1131           ('a' <= *value && *value <= 'z') ||
1132           ('0' <= *value && *value <= '9') || *value == '+' || *value == '-' ||
1133           *value == '.')) {
1134       return 0;
1135     }
1136   }
1137   return 1;
1138 }
1139 
1140 /* Generated by genmethodchartbl.py */
1141 static char VALID_METHOD_CHARS[] = {
1142     0 /* NUL  */, 0 /* SOH  */, 0 /* STX  */, 0 /* ETX  */,
1143     0 /* EOT  */, 0 /* ENQ  */, 0 /* ACK  */, 0 /* BEL  */,
1144     0 /* BS   */, 0 /* HT   */, 0 /* LF   */, 0 /* VT   */,
1145     0 /* FF   */, 0 /* CR   */, 0 /* SO   */, 0 /* SI   */,
1146     0 /* DLE  */, 0 /* DC1  */, 0 /* DC2  */, 0 /* DC3  */,
1147     0 /* DC4  */, 0 /* NAK  */, 0 /* SYN  */, 0 /* ETB  */,
1148     0 /* CAN  */, 0 /* EM   */, 0 /* SUB  */, 0 /* ESC  */,
1149     0 /* FS   */, 0 /* GS   */, 0 /* RS   */, 0 /* US   */,
1150     0 /* SPC  */, 1 /* !    */, 0 /* "    */, 1 /* #    */,
1151     1 /* $    */, 1 /* %    */, 1 /* &    */, 1 /* '    */,
1152     0 /* (    */, 0 /* )    */, 1 /* *    */, 1 /* +    */,
1153     0 /* ,    */, 1 /* -    */, 1 /* .    */, 0 /* /    */,
1154     1 /* 0    */, 1 /* 1    */, 1 /* 2    */, 1 /* 3    */,
1155     1 /* 4    */, 1 /* 5    */, 1 /* 6    */, 1 /* 7    */,
1156     1 /* 8    */, 1 /* 9    */, 0 /* :    */, 0 /* ;    */,
1157     0 /* <    */, 0 /* =    */, 0 /* >    */, 0 /* ?    */,
1158     0 /* @    */, 1 /* A    */, 1 /* B    */, 1 /* C    */,
1159     1 /* D    */, 1 /* E    */, 1 /* F    */, 1 /* G    */,
1160     1 /* H    */, 1 /* I    */, 1 /* J    */, 1 /* K    */,
1161     1 /* L    */, 1 /* M    */, 1 /* N    */, 1 /* O    */,
1162     1 /* P    */, 1 /* Q    */, 1 /* R    */, 1 /* S    */,
1163     1 /* T    */, 1 /* U    */, 1 /* V    */, 1 /* W    */,
1164     1 /* X    */, 1 /* Y    */, 1 /* Z    */, 0 /* [    */,
1165     0 /* \    */, 0 /* ]    */, 1 /* ^    */, 1 /* _    */,
1166     1 /* `    */, 1 /* a    */, 1 /* b    */, 1 /* c    */,
1167     1 /* d    */, 1 /* e    */, 1 /* f    */, 1 /* g    */,
1168     1 /* h    */, 1 /* i    */, 1 /* j    */, 1 /* k    */,
1169     1 /* l    */, 1 /* m    */, 1 /* n    */, 1 /* o    */,
1170     1 /* p    */, 1 /* q    */, 1 /* r    */, 1 /* s    */,
1171     1 /* t    */, 1 /* u    */, 1 /* v    */, 1 /* w    */,
1172     1 /* x    */, 1 /* y    */, 1 /* z    */, 0 /* {    */,
1173     1 /* |    */, 0 /* }    */, 1 /* ~    */, 0 /* DEL  */,
1174     0 /* 0x80 */, 0 /* 0x81 */, 0 /* 0x82 */, 0 /* 0x83 */,
1175     0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, 0 /* 0x87 */,
1176     0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
1177     0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */,
1178     0 /* 0x90 */, 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */,
1179     0 /* 0x94 */, 0 /* 0x95 */, 0 /* 0x96 */, 0 /* 0x97 */,
1180     0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, 0 /* 0x9b */,
1181     0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
1182     0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */,
1183     0 /* 0xa4 */, 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */,
1184     0 /* 0xa8 */, 0 /* 0xa9 */, 0 /* 0xaa */, 0 /* 0xab */,
1185     0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, 0 /* 0xaf */,
1186     0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
1187     0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */,
1188     0 /* 0xb8 */, 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */,
1189     0 /* 0xbc */, 0 /* 0xbd */, 0 /* 0xbe */, 0 /* 0xbf */,
1190     0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, 0 /* 0xc3 */,
1191     0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
1192     0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */,
1193     0 /* 0xcc */, 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */,
1194     0 /* 0xd0 */, 0 /* 0xd1 */, 0 /* 0xd2 */, 0 /* 0xd3 */,
1195     0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, 0 /* 0xd7 */,
1196     0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
1197     0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */,
1198     0 /* 0xe0 */, 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */,
1199     0 /* 0xe4 */, 0 /* 0xe5 */, 0 /* 0xe6 */, 0 /* 0xe7 */,
1200     0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, 0 /* 0xeb */,
1201     0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
1202     0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */,
1203     0 /* 0xf4 */, 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */,
1204     0 /* 0xf8 */, 0 /* 0xf9 */, 0 /* 0xfa */, 0 /* 0xfb */,
1205     0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, 0 /* 0xff */
1206 };
1207 
check_method(const uint8_t * value,size_t len)1208 static int check_method(const uint8_t *value, size_t len) {
1209   const uint8_t *last;
1210   if (len == 0) {
1211     return 0;
1212   }
1213   for (last = value + len; value != last; ++value) {
1214     if (!VALID_METHOD_CHARS[*value]) {
1215       return 0;
1216     }
1217   }
1218   return 1;
1219 }
1220 
1221 /* Generated by genpathchartbl.py */
1222 static char VALID_PATH_CHARS[] = {
1223     0 /* NUL  */, 0 /* SOH  */, 0 /* STX  */, 0 /* ETX  */,
1224     0 /* EOT  */, 0 /* ENQ  */, 0 /* ACK  */, 0 /* BEL  */,
1225     0 /* BS   */, 0 /* HT   */, 0 /* LF   */, 0 /* VT   */,
1226     0 /* FF   */, 0 /* CR   */, 0 /* SO   */, 0 /* SI   */,
1227     0 /* DLE  */, 0 /* DC1  */, 0 /* DC2  */, 0 /* DC3  */,
1228     0 /* DC4  */, 0 /* NAK  */, 0 /* SYN  */, 0 /* ETB  */,
1229     0 /* CAN  */, 0 /* EM   */, 0 /* SUB  */, 0 /* ESC  */,
1230     0 /* FS   */, 0 /* GS   */, 0 /* RS   */, 0 /* US   */,
1231     0 /* SPC  */, 1 /* !    */, 1 /* "    */, 1 /* #    */,
1232     1 /* $    */, 1 /* %    */, 1 /* &    */, 1 /* '    */,
1233     1 /* (    */, 1 /* )    */, 1 /* *    */, 1 /* +    */,
1234     1 /* ,    */, 1 /* -    */, 1 /* .    */, 1 /* /    */,
1235     1 /* 0    */, 1 /* 1    */, 1 /* 2    */, 1 /* 3    */,
1236     1 /* 4    */, 1 /* 5    */, 1 /* 6    */, 1 /* 7    */,
1237     1 /* 8    */, 1 /* 9    */, 1 /* :    */, 1 /* ;    */,
1238     1 /* <    */, 1 /* =    */, 1 /* >    */, 1 /* ?    */,
1239     1 /* @    */, 1 /* A    */, 1 /* B    */, 1 /* C    */,
1240     1 /* D    */, 1 /* E    */, 1 /* F    */, 1 /* G    */,
1241     1 /* H    */, 1 /* I    */, 1 /* J    */, 1 /* K    */,
1242     1 /* L    */, 1 /* M    */, 1 /* N    */, 1 /* O    */,
1243     1 /* P    */, 1 /* Q    */, 1 /* R    */, 1 /* S    */,
1244     1 /* T    */, 1 /* U    */, 1 /* V    */, 1 /* W    */,
1245     1 /* X    */, 1 /* Y    */, 1 /* Z    */, 1 /* [    */,
1246     1 /* \    */, 1 /* ]    */, 1 /* ^    */, 1 /* _    */,
1247     1 /* `    */, 1 /* a    */, 1 /* b    */, 1 /* c    */,
1248     1 /* d    */, 1 /* e    */, 1 /* f    */, 1 /* g    */,
1249     1 /* h    */, 1 /* i    */, 1 /* j    */, 1 /* k    */,
1250     1 /* l    */, 1 /* m    */, 1 /* n    */, 1 /* o    */,
1251     1 /* p    */, 1 /* q    */, 1 /* r    */, 1 /* s    */,
1252     1 /* t    */, 1 /* u    */, 1 /* v    */, 1 /* w    */,
1253     1 /* x    */, 1 /* y    */, 1 /* z    */, 1 /* {    */,
1254     1 /* |    */, 1 /* }    */, 1 /* ~    */, 0 /* DEL  */,
1255     1 /* 0x80 */, 1 /* 0x81 */, 1 /* 0x82 */, 1 /* 0x83 */,
1256     1 /* 0x84 */, 1 /* 0x85 */, 1 /* 0x86 */, 1 /* 0x87 */,
1257     1 /* 0x88 */, 1 /* 0x89 */, 1 /* 0x8a */, 1 /* 0x8b */,
1258     1 /* 0x8c */, 1 /* 0x8d */, 1 /* 0x8e */, 1 /* 0x8f */,
1259     1 /* 0x90 */, 1 /* 0x91 */, 1 /* 0x92 */, 1 /* 0x93 */,
1260     1 /* 0x94 */, 1 /* 0x95 */, 1 /* 0x96 */, 1 /* 0x97 */,
1261     1 /* 0x98 */, 1 /* 0x99 */, 1 /* 0x9a */, 1 /* 0x9b */,
1262     1 /* 0x9c */, 1 /* 0x9d */, 1 /* 0x9e */, 1 /* 0x9f */,
1263     1 /* 0xa0 */, 1 /* 0xa1 */, 1 /* 0xa2 */, 1 /* 0xa3 */,
1264     1 /* 0xa4 */, 1 /* 0xa5 */, 1 /* 0xa6 */, 1 /* 0xa7 */,
1265     1 /* 0xa8 */, 1 /* 0xa9 */, 1 /* 0xaa */, 1 /* 0xab */,
1266     1 /* 0xac */, 1 /* 0xad */, 1 /* 0xae */, 1 /* 0xaf */,
1267     1 /* 0xb0 */, 1 /* 0xb1 */, 1 /* 0xb2 */, 1 /* 0xb3 */,
1268     1 /* 0xb4 */, 1 /* 0xb5 */, 1 /* 0xb6 */, 1 /* 0xb7 */,
1269     1 /* 0xb8 */, 1 /* 0xb9 */, 1 /* 0xba */, 1 /* 0xbb */,
1270     1 /* 0xbc */, 1 /* 0xbd */, 1 /* 0xbe */, 1 /* 0xbf */,
1271     1 /* 0xc0 */, 1 /* 0xc1 */, 1 /* 0xc2 */, 1 /* 0xc3 */,
1272     1 /* 0xc4 */, 1 /* 0xc5 */, 1 /* 0xc6 */, 1 /* 0xc7 */,
1273     1 /* 0xc8 */, 1 /* 0xc9 */, 1 /* 0xca */, 1 /* 0xcb */,
1274     1 /* 0xcc */, 1 /* 0xcd */, 1 /* 0xce */, 1 /* 0xcf */,
1275     1 /* 0xd0 */, 1 /* 0xd1 */, 1 /* 0xd2 */, 1 /* 0xd3 */,
1276     1 /* 0xd4 */, 1 /* 0xd5 */, 1 /* 0xd6 */, 1 /* 0xd7 */,
1277     1 /* 0xd8 */, 1 /* 0xd9 */, 1 /* 0xda */, 1 /* 0xdb */,
1278     1 /* 0xdc */, 1 /* 0xdd */, 1 /* 0xde */, 1 /* 0xdf */,
1279     1 /* 0xe0 */, 1 /* 0xe1 */, 1 /* 0xe2 */, 1 /* 0xe3 */,
1280     1 /* 0xe4 */, 1 /* 0xe5 */, 1 /* 0xe6 */, 1 /* 0xe7 */,
1281     1 /* 0xe8 */, 1 /* 0xe9 */, 1 /* 0xea */, 1 /* 0xeb */,
1282     1 /* 0xec */, 1 /* 0xed */, 1 /* 0xee */, 1 /* 0xef */,
1283     1 /* 0xf0 */, 1 /* 0xf1 */, 1 /* 0xf2 */, 1 /* 0xf3 */,
1284     1 /* 0xf4 */, 1 /* 0xf5 */, 1 /* 0xf6 */, 1 /* 0xf7 */,
1285     1 /* 0xf8 */, 1 /* 0xf9 */, 1 /* 0xfa */, 1 /* 0xfb */,
1286     1 /* 0xfc */, 1 /* 0xfd */, 1 /* 0xfe */, 1 /* 0xff */
1287 };
1288 
check_path(const uint8_t * value,size_t len)1289 static int check_path(const uint8_t *value, size_t len) {
1290   const uint8_t *last;
1291   for (last = value + len; value != last; ++value) {
1292     if (!VALID_PATH_CHARS[*value]) {
1293       return 0;
1294     }
1295   }
1296   return 1;
1297 }
1298 
nghttp3_http_on_header(nghttp3_http_state * http,nghttp3_qpack_nv * nv,int request,int trailers,int connect_protocol)1299 int nghttp3_http_on_header(nghttp3_http_state *http, nghttp3_qpack_nv *nv,
1300                            int request, int trailers, int connect_protocol) {
1301   int rv;
1302   size_t i;
1303   uint8_t c;
1304 
1305   if (!nghttp3_check_header_name(nv->name->base, nv->name->len)) {
1306     if (nv->name->len > 0 && nv->name->base[0] == ':') {
1307       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
1308     }
1309     /* header field name must be lower-cased without exception */
1310     for (i = 0; i < nv->name->len; ++i) {
1311       c = nv->name->base[i];
1312       if ('A' <= c && c <= 'Z') {
1313         return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
1314       }
1315     }
1316     /* When ignoring regular header fields, we set this flag so that
1317        we still enforce header field ordering rule for pseudo header
1318        fields. */
1319     http->flags |= NGHTTP3_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED;
1320     return NGHTTP3_ERR_REMOVE_HTTP_HEADER;
1321   }
1322 
1323   assert(nv->name->len > 0);
1324 
1325   switch (nv->token) {
1326   case NGHTTP3_QPACK_TOKEN__METHOD:
1327     rv = check_method(nv->value->base, nv->value->len);
1328     break;
1329   case NGHTTP3_QPACK_TOKEN__SCHEME:
1330     rv = check_scheme(nv->value->base, nv->value->len);
1331     break;
1332   case NGHTTP3_QPACK_TOKEN__AUTHORITY:
1333   case NGHTTP3_QPACK_TOKEN_HOST:
1334     rv = check_authority(nv->value->base, nv->value->len);
1335     break;
1336   case NGHTTP3_QPACK_TOKEN__PATH:
1337     rv = check_path(nv->value->base, nv->value->len);
1338     break;
1339   default:
1340     rv = nghttp3_check_header_value(nv->value->base, nv->value->len);
1341   }
1342 
1343   if (rv == 0) {
1344     if (nv->name->base[0] == ':') {
1345       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
1346     }
1347     /* When ignoring regular header fields, we set this flag so that
1348        we still enforce header field ordering rule for pseudo header
1349        fields. */
1350     http->flags |= NGHTTP3_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED;
1351     return NGHTTP3_ERR_REMOVE_HTTP_HEADER;
1352   }
1353 
1354   if (request) {
1355     rv = http_request_on_header(http, nv, trailers, connect_protocol);
1356   } else {
1357     rv = http_response_on_header(http, nv, trailers);
1358   }
1359 
1360   if (nv->name->base[0] != ':') {
1361     switch (rv) {
1362     case 0:
1363     case NGHTTP3_ERR_REMOVE_HTTP_HEADER:
1364       http->flags |= NGHTTP3_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED;
1365       break;
1366     }
1367   }
1368 
1369   return rv;
1370 }
1371 
nghttp3_http_on_request_headers(nghttp3_http_state * http)1372 int nghttp3_http_on_request_headers(nghttp3_http_state *http) {
1373   if (!(http->flags & NGHTTP3_HTTP_FLAG__PROTOCOL) &&
1374       (http->flags & NGHTTP3_HTTP_FLAG_METH_CONNECT)) {
1375     if ((http->flags & (NGHTTP3_HTTP_FLAG__SCHEME | NGHTTP3_HTTP_FLAG__PATH)) ||
1376         (http->flags & NGHTTP3_HTTP_FLAG__AUTHORITY) == 0) {
1377       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
1378     }
1379     http->content_length = -1;
1380   } else {
1381     if ((http->flags & NGHTTP3_HTTP_FLAG_REQ_HEADERS) !=
1382             NGHTTP3_HTTP_FLAG_REQ_HEADERS ||
1383         (http->flags &
1384          (NGHTTP3_HTTP_FLAG__AUTHORITY | NGHTTP3_HTTP_FLAG_HOST)) == 0) {
1385       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
1386     }
1387     if ((http->flags & NGHTTP3_HTTP_FLAG__PROTOCOL) &&
1388         ((http->flags & NGHTTP3_HTTP_FLAG_METH_CONNECT) == 0 ||
1389          (http->flags & NGHTTP3_HTTP_FLAG__AUTHORITY) == 0)) {
1390       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
1391     }
1392     if (!check_path_flags(http)) {
1393       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
1394     }
1395   }
1396 
1397   return 0;
1398 }
1399 
nghttp3_http_on_response_headers(nghttp3_http_state * http)1400 int nghttp3_http_on_response_headers(nghttp3_http_state *http) {
1401   if ((http->flags & NGHTTP3_HTTP_FLAG__STATUS) == 0) {
1402     return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
1403   }
1404 
1405   if (http->status_code / 100 == 1) {
1406     /* non-final response */
1407     http->flags = (uint16_t)((http->flags & NGHTTP3_HTTP_FLAG_METH_ALL) |
1408                              NGHTTP3_HTTP_FLAG_EXPECT_FINAL_RESPONSE);
1409     http->content_length = -1;
1410     http->status_code = -1;
1411     return 0;
1412   }
1413 
1414   http->flags =
1415       (uint16_t)(http->flags & ~NGHTTP3_HTTP_FLAG_EXPECT_FINAL_RESPONSE);
1416 
1417   if (!expect_response_body(http)) {
1418     http->content_length = 0;
1419   } else if (http->flags & NGHTTP3_HTTP_FLAG_METH_CONNECT) {
1420     http->content_length = -1;
1421   }
1422 
1423   return 0;
1424 }
1425 
nghttp3_http_on_remote_end_stream(nghttp3_stream * stream)1426 int nghttp3_http_on_remote_end_stream(nghttp3_stream *stream) {
1427   if ((stream->rx.http.flags & NGHTTP3_HTTP_FLAG_EXPECT_FINAL_RESPONSE) ||
1428       (stream->rx.http.content_length != -1 &&
1429        stream->rx.http.content_length != stream->rx.http.recv_content_length)) {
1430     return NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING;
1431   }
1432 
1433   return 0;
1434 }
1435 
nghttp3_http_on_data_chunk(nghttp3_stream * stream,size_t n)1436 int nghttp3_http_on_data_chunk(nghttp3_stream *stream, size_t n) {
1437   stream->rx.http.recv_content_length += (int64_t)n;
1438 
1439   if ((stream->rx.http.flags & NGHTTP3_HTTP_FLAG_EXPECT_FINAL_RESPONSE) ||
1440       (stream->rx.http.content_length != -1 &&
1441        stream->rx.http.recv_content_length > stream->rx.http.content_length)) {
1442     return NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING;
1443   }
1444 
1445   return 0;
1446 }
1447 
nghttp3_http_record_request_method(nghttp3_stream * stream,const nghttp3_nv * nva,size_t nvlen)1448 void nghttp3_http_record_request_method(nghttp3_stream *stream,
1449                                         const nghttp3_nv *nva, size_t nvlen) {
1450   size_t i;
1451   const nghttp3_nv *nv;
1452 
1453   /* TODO we should do this strictly. */
1454   for (i = 0; i < nvlen; ++i) {
1455     nv = &nva[i];
1456     if (!(nv->namelen == 7 && nv->name[6] == 'd' &&
1457           memcmp(":metho", nv->name, nv->namelen - 1) == 0)) {
1458       continue;
1459     }
1460     if (lstreq("CONNECT", nv->value, nv->valuelen)) {
1461       stream->rx.http.flags |= NGHTTP3_HTTP_FLAG_METH_CONNECT;
1462       return;
1463     }
1464     if (lstreq("HEAD", nv->value, nv->valuelen)) {
1465       stream->rx.http.flags |= NGHTTP3_HTTP_FLAG_METH_HEAD;
1466       return;
1467     }
1468     return;
1469   }
1470 }
1471 
1472 /* Generated by gennmchartbl.py */
1473 static const int VALID_HD_NAME_CHARS[] = {
1474     0 /* NUL  */, 0 /* SOH  */, 0 /* STX  */, 0 /* ETX  */,
1475     0 /* EOT  */, 0 /* ENQ  */, 0 /* ACK  */, 0 /* BEL  */,
1476     0 /* BS   */, 0 /* HT   */, 0 /* LF   */, 0 /* VT   */,
1477     0 /* FF   */, 0 /* CR   */, 0 /* SO   */, 0 /* SI   */,
1478     0 /* DLE  */, 0 /* DC1  */, 0 /* DC2  */, 0 /* DC3  */,
1479     0 /* DC4  */, 0 /* NAK  */, 0 /* SYN  */, 0 /* ETB  */,
1480     0 /* CAN  */, 0 /* EM   */, 0 /* SUB  */, 0 /* ESC  */,
1481     0 /* FS   */, 0 /* GS   */, 0 /* RS   */, 0 /* US   */,
1482     0 /* SPC  */, 1 /* !    */, 0 /* "    */, 1 /* #    */,
1483     1 /* $    */, 1 /* %    */, 1 /* &    */, 1 /* '    */,
1484     0 /* (    */, 0 /* )    */, 1 /* *    */, 1 /* +    */,
1485     0 /* ,    */, 1 /* -    */, 1 /* .    */, 0 /* /    */,
1486     1 /* 0    */, 1 /* 1    */, 1 /* 2    */, 1 /* 3    */,
1487     1 /* 4    */, 1 /* 5    */, 1 /* 6    */, 1 /* 7    */,
1488     1 /* 8    */, 1 /* 9    */, 0 /* :    */, 0 /* ;    */,
1489     0 /* <    */, 0 /* =    */, 0 /* >    */, 0 /* ?    */,
1490     0 /* @    */, 0 /* A    */, 0 /* B    */, 0 /* C    */,
1491     0 /* D    */, 0 /* E    */, 0 /* F    */, 0 /* G    */,
1492     0 /* H    */, 0 /* I    */, 0 /* J    */, 0 /* K    */,
1493     0 /* L    */, 0 /* M    */, 0 /* N    */, 0 /* O    */,
1494     0 /* P    */, 0 /* Q    */, 0 /* R    */, 0 /* S    */,
1495     0 /* T    */, 0 /* U    */, 0 /* V    */, 0 /* W    */,
1496     0 /* X    */, 0 /* Y    */, 0 /* Z    */, 0 /* [    */,
1497     0 /* \    */, 0 /* ]    */, 1 /* ^    */, 1 /* _    */,
1498     1 /* `    */, 1 /* a    */, 1 /* b    */, 1 /* c    */,
1499     1 /* d    */, 1 /* e    */, 1 /* f    */, 1 /* g    */,
1500     1 /* h    */, 1 /* i    */, 1 /* j    */, 1 /* k    */,
1501     1 /* l    */, 1 /* m    */, 1 /* n    */, 1 /* o    */,
1502     1 /* p    */, 1 /* q    */, 1 /* r    */, 1 /* s    */,
1503     1 /* t    */, 1 /* u    */, 1 /* v    */, 1 /* w    */,
1504     1 /* x    */, 1 /* y    */, 1 /* z    */, 0 /* {    */,
1505     1 /* |    */, 0 /* }    */, 1 /* ~    */, 0 /* DEL  */,
1506     0 /* 0x80 */, 0 /* 0x81 */, 0 /* 0x82 */, 0 /* 0x83 */,
1507     0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, 0 /* 0x87 */,
1508     0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
1509     0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */,
1510     0 /* 0x90 */, 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */,
1511     0 /* 0x94 */, 0 /* 0x95 */, 0 /* 0x96 */, 0 /* 0x97 */,
1512     0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, 0 /* 0x9b */,
1513     0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
1514     0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */,
1515     0 /* 0xa4 */, 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */,
1516     0 /* 0xa8 */, 0 /* 0xa9 */, 0 /* 0xaa */, 0 /* 0xab */,
1517     0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, 0 /* 0xaf */,
1518     0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
1519     0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */,
1520     0 /* 0xb8 */, 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */,
1521     0 /* 0xbc */, 0 /* 0xbd */, 0 /* 0xbe */, 0 /* 0xbf */,
1522     0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, 0 /* 0xc3 */,
1523     0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
1524     0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */,
1525     0 /* 0xcc */, 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */,
1526     0 /* 0xd0 */, 0 /* 0xd1 */, 0 /* 0xd2 */, 0 /* 0xd3 */,
1527     0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, 0 /* 0xd7 */,
1528     0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
1529     0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */,
1530     0 /* 0xe0 */, 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */,
1531     0 /* 0xe4 */, 0 /* 0xe5 */, 0 /* 0xe6 */, 0 /* 0xe7 */,
1532     0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, 0 /* 0xeb */,
1533     0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
1534     0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */,
1535     0 /* 0xf4 */, 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */,
1536     0 /* 0xf8 */, 0 /* 0xf9 */, 0 /* 0xfa */, 0 /* 0xfb */,
1537     0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, 0 /* 0xff */
1538 };
1539 
nghttp3_check_header_name(const uint8_t * name,size_t len)1540 int nghttp3_check_header_name(const uint8_t *name, size_t len) {
1541   const uint8_t *last;
1542   if (len == 0) {
1543     return 0;
1544   }
1545   if (*name == ':') {
1546     if (len == 1) {
1547       return 0;
1548     }
1549     ++name;
1550     --len;
1551   }
1552   for (last = name + len; name != last; ++name) {
1553     if (!VALID_HD_NAME_CHARS[*name]) {
1554       return 0;
1555     }
1556   }
1557   return 1;
1558 }
1559 
1560 /* Generated by genvchartbl.py */
1561 static const int VALID_HD_VALUE_CHARS[] = {
1562     0 /* NUL  */, 0 /* SOH  */, 0 /* STX  */, 0 /* ETX  */,
1563     0 /* EOT  */, 0 /* ENQ  */, 0 /* ACK  */, 0 /* BEL  */,
1564     0 /* BS   */, 1 /* HT   */, 0 /* LF   */, 0 /* VT   */,
1565     0 /* FF   */, 0 /* CR   */, 0 /* SO   */, 0 /* SI   */,
1566     0 /* DLE  */, 0 /* DC1  */, 0 /* DC2  */, 0 /* DC3  */,
1567     0 /* DC4  */, 0 /* NAK  */, 0 /* SYN  */, 0 /* ETB  */,
1568     0 /* CAN  */, 0 /* EM   */, 0 /* SUB  */, 0 /* ESC  */,
1569     0 /* FS   */, 0 /* GS   */, 0 /* RS   */, 0 /* US   */,
1570     1 /* SPC  */, 1 /* !    */, 1 /* "    */, 1 /* #    */,
1571     1 /* $    */, 1 /* %    */, 1 /* &    */, 1 /* '    */,
1572     1 /* (    */, 1 /* )    */, 1 /* *    */, 1 /* +    */,
1573     1 /* ,    */, 1 /* -    */, 1 /* .    */, 1 /* /    */,
1574     1 /* 0    */, 1 /* 1    */, 1 /* 2    */, 1 /* 3    */,
1575     1 /* 4    */, 1 /* 5    */, 1 /* 6    */, 1 /* 7    */,
1576     1 /* 8    */, 1 /* 9    */, 1 /* :    */, 1 /* ;    */,
1577     1 /* <    */, 1 /* =    */, 1 /* >    */, 1 /* ?    */,
1578     1 /* @    */, 1 /* A    */, 1 /* B    */, 1 /* C    */,
1579     1 /* D    */, 1 /* E    */, 1 /* F    */, 1 /* G    */,
1580     1 /* H    */, 1 /* I    */, 1 /* J    */, 1 /* K    */,
1581     1 /* L    */, 1 /* M    */, 1 /* N    */, 1 /* O    */,
1582     1 /* P    */, 1 /* Q    */, 1 /* R    */, 1 /* S    */,
1583     1 /* T    */, 1 /* U    */, 1 /* V    */, 1 /* W    */,
1584     1 /* X    */, 1 /* Y    */, 1 /* Z    */, 1 /* [    */,
1585     1 /* \    */, 1 /* ]    */, 1 /* ^    */, 1 /* _    */,
1586     1 /* `    */, 1 /* a    */, 1 /* b    */, 1 /* c    */,
1587     1 /* d    */, 1 /* e    */, 1 /* f    */, 1 /* g    */,
1588     1 /* h    */, 1 /* i    */, 1 /* j    */, 1 /* k    */,
1589     1 /* l    */, 1 /* m    */, 1 /* n    */, 1 /* o    */,
1590     1 /* p    */, 1 /* q    */, 1 /* r    */, 1 /* s    */,
1591     1 /* t    */, 1 /* u    */, 1 /* v    */, 1 /* w    */,
1592     1 /* x    */, 1 /* y    */, 1 /* z    */, 1 /* {    */,
1593     1 /* |    */, 1 /* }    */, 1 /* ~    */, 0 /* DEL  */,
1594     1 /* 0x80 */, 1 /* 0x81 */, 1 /* 0x82 */, 1 /* 0x83 */,
1595     1 /* 0x84 */, 1 /* 0x85 */, 1 /* 0x86 */, 1 /* 0x87 */,
1596     1 /* 0x88 */, 1 /* 0x89 */, 1 /* 0x8a */, 1 /* 0x8b */,
1597     1 /* 0x8c */, 1 /* 0x8d */, 1 /* 0x8e */, 1 /* 0x8f */,
1598     1 /* 0x90 */, 1 /* 0x91 */, 1 /* 0x92 */, 1 /* 0x93 */,
1599     1 /* 0x94 */, 1 /* 0x95 */, 1 /* 0x96 */, 1 /* 0x97 */,
1600     1 /* 0x98 */, 1 /* 0x99 */, 1 /* 0x9a */, 1 /* 0x9b */,
1601     1 /* 0x9c */, 1 /* 0x9d */, 1 /* 0x9e */, 1 /* 0x9f */,
1602     1 /* 0xa0 */, 1 /* 0xa1 */, 1 /* 0xa2 */, 1 /* 0xa3 */,
1603     1 /* 0xa4 */, 1 /* 0xa5 */, 1 /* 0xa6 */, 1 /* 0xa7 */,
1604     1 /* 0xa8 */, 1 /* 0xa9 */, 1 /* 0xaa */, 1 /* 0xab */,
1605     1 /* 0xac */, 1 /* 0xad */, 1 /* 0xae */, 1 /* 0xaf */,
1606     1 /* 0xb0 */, 1 /* 0xb1 */, 1 /* 0xb2 */, 1 /* 0xb3 */,
1607     1 /* 0xb4 */, 1 /* 0xb5 */, 1 /* 0xb6 */, 1 /* 0xb7 */,
1608     1 /* 0xb8 */, 1 /* 0xb9 */, 1 /* 0xba */, 1 /* 0xbb */,
1609     1 /* 0xbc */, 1 /* 0xbd */, 1 /* 0xbe */, 1 /* 0xbf */,
1610     1 /* 0xc0 */, 1 /* 0xc1 */, 1 /* 0xc2 */, 1 /* 0xc3 */,
1611     1 /* 0xc4 */, 1 /* 0xc5 */, 1 /* 0xc6 */, 1 /* 0xc7 */,
1612     1 /* 0xc8 */, 1 /* 0xc9 */, 1 /* 0xca */, 1 /* 0xcb */,
1613     1 /* 0xcc */, 1 /* 0xcd */, 1 /* 0xce */, 1 /* 0xcf */,
1614     1 /* 0xd0 */, 1 /* 0xd1 */, 1 /* 0xd2 */, 1 /* 0xd3 */,
1615     1 /* 0xd4 */, 1 /* 0xd5 */, 1 /* 0xd6 */, 1 /* 0xd7 */,
1616     1 /* 0xd8 */, 1 /* 0xd9 */, 1 /* 0xda */, 1 /* 0xdb */,
1617     1 /* 0xdc */, 1 /* 0xdd */, 1 /* 0xde */, 1 /* 0xdf */,
1618     1 /* 0xe0 */, 1 /* 0xe1 */, 1 /* 0xe2 */, 1 /* 0xe3 */,
1619     1 /* 0xe4 */, 1 /* 0xe5 */, 1 /* 0xe6 */, 1 /* 0xe7 */,
1620     1 /* 0xe8 */, 1 /* 0xe9 */, 1 /* 0xea */, 1 /* 0xeb */,
1621     1 /* 0xec */, 1 /* 0xed */, 1 /* 0xee */, 1 /* 0xef */,
1622     1 /* 0xf0 */, 1 /* 0xf1 */, 1 /* 0xf2 */, 1 /* 0xf3 */,
1623     1 /* 0xf4 */, 1 /* 0xf5 */, 1 /* 0xf6 */, 1 /* 0xf7 */,
1624     1 /* 0xf8 */, 1 /* 0xf9 */, 1 /* 0xfa */, 1 /* 0xfb */,
1625     1 /* 0xfc */, 1 /* 0xfd */, 1 /* 0xfe */, 1 /* 0xff */
1626 };
1627 
nghttp3_check_header_value(const uint8_t * value,size_t len)1628 int nghttp3_check_header_value(const uint8_t *value, size_t len) {
1629   const uint8_t *last;
1630   for (last = value + len; value != last; ++value) {
1631     if (!VALID_HD_VALUE_CHARS[*value]) {
1632       return 0;
1633     }
1634   }
1635   return 1;
1636 }
1637