• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
39 /*
40  * memieq returns 1 if the data pointed by |a| of length |n| equals to
41  * |b| of the same length in case-insensitive manner.  The data
42  * pointed by |a| must not include upper cased letters (A-Z).
43  */
memieq(const void * a,const void * b,size_t n)44 static int memieq(const void *a, const void *b, size_t n) {
45   size_t i;
46   const uint8_t *aa = a, *bb = b;
47 
48   for (i = 0; i < n; ++i) {
49     if (aa[i] != downcase(bb[i])) {
50       return 0;
51     }
52   }
53   return 1;
54 }
55 
56 #define lstrieq(A, B, N) ((sizeof((A)) - 1) == (N) && memieq((A), (B), (N)))
57 
parse_uint(const uint8_t * s,size_t len)58 static int64_t parse_uint(const uint8_t *s, size_t len) {
59   int64_t n = 0;
60   size_t i;
61   if (len == 0) {
62     return -1;
63   }
64   for (i = 0; i < len; ++i) {
65     if ('0' <= s[i] && s[i] <= '9') {
66       if (n > INT64_MAX / 10) {
67         return -1;
68       }
69       n *= 10;
70       if (n > INT64_MAX - (s[i] - '0')) {
71         return -1;
72       }
73       n += s[i] - '0';
74       continue;
75     }
76     return -1;
77   }
78   return n;
79 }
80 
check_pseudo_header(nghttp3_http_state * http,const nghttp3_qpack_nv * nv,uint32_t flag)81 static int check_pseudo_header(nghttp3_http_state *http,
82                                const nghttp3_qpack_nv *nv, uint32_t flag) {
83   if ((http->flags & flag) || nv->value->len == 0) {
84     return 0;
85   }
86   http->flags |= flag;
87   return 1;
88 }
89 
expect_response_body(nghttp3_http_state * http)90 static int expect_response_body(nghttp3_http_state *http) {
91   return (http->flags & NGHTTP3_HTTP_FLAG_METH_HEAD) == 0 &&
92          http->status_code / 100 != 1 && http->status_code != 304 &&
93          http->status_code != 204;
94 }
95 
96 /* For "http" or "https" URIs, OPTIONS request may have "*" in :path
97    header field to represent system-wide OPTIONS request.  Otherwise,
98    :path header field value must start with "/".  This function must
99    be called after ":method" header field was received.  This function
100    returns nonzero if path is valid.*/
check_path_flags(nghttp3_http_state * http)101 static int check_path_flags(nghttp3_http_state *http) {
102   return (http->flags & NGHTTP3_HTTP_FLAG_SCHEME_HTTP) == 0 ||
103          ((http->flags & NGHTTP3_HTTP_FLAG_PATH_REGULAR) ||
104           ((http->flags & NGHTTP3_HTTP_FLAG_METH_OPTIONS) &&
105            (http->flags & NGHTTP3_HTTP_FLAG_PATH_ASTERISK)));
106 }
107 
108 /* Generated by genchartbl.py */
109 static const int SF_KEY_CHARS[] = {
110     0 /* NUL  */, 0 /* SOH  */, 0 /* STX  */, 0 /* ETX  */, 0 /* EOT  */,
111     0 /* ENQ  */, 0 /* ACK  */, 0 /* BEL  */, 0 /* BS   */, 0 /* HT   */,
112     0 /* LF   */, 0 /* VT   */, 0 /* FF   */, 0 /* CR   */, 0 /* SO   */,
113     0 /* SI   */, 0 /* DLE  */, 0 /* DC1  */, 0 /* DC2  */, 0 /* DC3  */,
114     0 /* DC4  */, 0 /* NAK  */, 0 /* SYN  */, 0 /* ETB  */, 0 /* CAN  */,
115     0 /* EM   */, 0 /* SUB  */, 0 /* ESC  */, 0 /* FS   */, 0 /* GS   */,
116     0 /* RS   */, 0 /* US   */, 0 /* SPC  */, 0 /* !    */, 0 /* "    */,
117     0 /* #    */, 0 /* $    */, 0 /* %    */, 0 /* &    */, 0 /* '    */,
118     0 /* (    */, 0 /* )    */, 1 /* *    */, 0 /* +    */, 0 /* ,    */,
119     1 /* -    */, 1 /* .    */, 0 /* /    */, 1 /* 0    */, 1 /* 1    */,
120     1 /* 2    */, 1 /* 3    */, 1 /* 4    */, 1 /* 5    */, 1 /* 6    */,
121     1 /* 7    */, 1 /* 8    */, 1 /* 9    */, 0 /* :    */, 0 /* ;    */,
122     0 /* <    */, 0 /* =    */, 0 /* >    */, 0 /* ?    */, 0 /* @    */,
123     0 /* A    */, 0 /* B    */, 0 /* C    */, 0 /* D    */, 0 /* E    */,
124     0 /* F    */, 0 /* G    */, 0 /* H    */, 0 /* I    */, 0 /* J    */,
125     0 /* K    */, 0 /* L    */, 0 /* M    */, 0 /* N    */, 0 /* O    */,
126     0 /* P    */, 0 /* Q    */, 0 /* R    */, 0 /* S    */, 0 /* T    */,
127     0 /* U    */, 0 /* V    */, 0 /* W    */, 0 /* X    */, 0 /* Y    */,
128     0 /* Z    */, 0 /* [    */, 0 /* \    */, 0 /* ]    */, 0 /* ^    */,
129     1 /* _    */, 0 /* `    */, 1 /* a    */, 1 /* b    */, 1 /* c    */,
130     1 /* d    */, 1 /* e    */, 1 /* f    */, 1 /* g    */, 1 /* h    */,
131     1 /* i    */, 1 /* j    */, 1 /* k    */, 1 /* l    */, 1 /* m    */,
132     1 /* n    */, 1 /* o    */, 1 /* p    */, 1 /* q    */, 1 /* r    */,
133     1 /* s    */, 1 /* t    */, 1 /* u    */, 1 /* v    */, 1 /* w    */,
134     1 /* x    */, 1 /* y    */, 1 /* z    */, 0 /* {    */, 0 /* |    */,
135     0 /* }    */, 0 /* ~    */, 0 /* DEL  */, 0 /* 0x80 */, 0 /* 0x81 */,
136     0 /* 0x82 */, 0 /* 0x83 */, 0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */,
137     0 /* 0x87 */, 0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
138     0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */, 0 /* 0x90 */,
139     0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */, 0 /* 0x94 */, 0 /* 0x95 */,
140     0 /* 0x96 */, 0 /* 0x97 */, 0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */,
141     0 /* 0x9b */, 0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
142     0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */, 0 /* 0xa4 */,
143     0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */, 0 /* 0xa8 */, 0 /* 0xa9 */,
144     0 /* 0xaa */, 0 /* 0xab */, 0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */,
145     0 /* 0xaf */, 0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
146     0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */, 0 /* 0xb8 */,
147     0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */, 0 /* 0xbc */, 0 /* 0xbd */,
148     0 /* 0xbe */, 0 /* 0xbf */, 0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */,
149     0 /* 0xc3 */, 0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
150     0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */, 0 /* 0xcc */,
151     0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */, 0 /* 0xd0 */, 0 /* 0xd1 */,
152     0 /* 0xd2 */, 0 /* 0xd3 */, 0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */,
153     0 /* 0xd7 */, 0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
154     0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */, 0 /* 0xe0 */,
155     0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */, 0 /* 0xe4 */, 0 /* 0xe5 */,
156     0 /* 0xe6 */, 0 /* 0xe7 */, 0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */,
157     0 /* 0xeb */, 0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
158     0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */, 0 /* 0xf4 */,
159     0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */, 0 /* 0xf8 */, 0 /* 0xf9 */,
160     0 /* 0xfa */, 0 /* 0xfb */, 0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */,
161     0 /* 0xff */,
162 };
163 
sf_parse_key(const uint8_t * begin,const uint8_t * end)164 static nghttp3_ssize sf_parse_key(const uint8_t *begin, const uint8_t *end) {
165   const uint8_t *p = begin;
166 
167   if ((*p < 'a' || 'z' < *p) && *p != '*') {
168     return -1;
169   }
170 
171   for (; p != end && SF_KEY_CHARS[*p]; ++p)
172     ;
173 
174   return p - begin;
175 }
176 
sf_parse_integer_or_decimal(nghttp3_sf_value * dest,const uint8_t * begin,const uint8_t * end)177 static nghttp3_ssize sf_parse_integer_or_decimal(nghttp3_sf_value *dest,
178                                                  const uint8_t *begin,
179                                                  const uint8_t *end) {
180   const uint8_t *p = begin;
181   int sign = 1;
182   int64_t value = 0;
183   int type = NGHTTP3_SF_VALUE_TYPE_INTEGER;
184   size_t len = 0;
185   size_t fpos = 0;
186   size_t i;
187 
188   if (*p == '-') {
189     if (++p == end) {
190       return -1;
191     }
192 
193     sign = -1;
194   }
195 
196   if (*p < '0' || '9' < *p) {
197     return -1;
198   }
199 
200   for (; p != end; ++p) {
201     switch (*p) {
202     case '0':
203     case '1':
204     case '2':
205     case '3':
206     case '4':
207     case '5':
208     case '6':
209     case '7':
210     case '8':
211     case '9':
212       value *= 10;
213       value += *p - '0';
214 
215       if (++len > 15) {
216         return -1;
217       }
218 
219       break;
220     case '.':
221       if (type != NGHTTP3_SF_VALUE_TYPE_INTEGER) {
222         goto fin;
223       }
224 
225       if (len > 12) {
226         return -1;
227       }
228       fpos = len;
229       type = NGHTTP3_SF_VALUE_TYPE_DECIMAL;
230 
231       break;
232     default:
233       goto fin;
234     };
235   }
236 
237 fin:
238   switch (type) {
239   case NGHTTP3_SF_VALUE_TYPE_INTEGER:
240     if (dest) {
241       dest->type = (uint8_t)type;
242       dest->i = value * sign;
243     }
244 
245     return p - begin;
246   case NGHTTP3_SF_VALUE_TYPE_DECIMAL:
247     if (fpos == len || len - fpos > 3) {
248       return -1;
249     }
250 
251     if (dest) {
252       dest->type = (uint8_t)type;
253       dest->d = (double)value;
254       for (i = len - fpos; i > 0; --i) {
255         dest->d /= (double)10;
256       }
257       dest->d *= sign;
258     }
259 
260     return p - begin;
261   default:
262     assert(0);
263     abort();
264   }
265 }
266 
267 /* Generated by genchartbl.py */
268 static const int SF_DQUOTE_CHARS[] = {
269     0 /* NUL  */, 0 /* SOH  */, 0 /* STX  */, 0 /* ETX  */, 0 /* EOT  */,
270     0 /* ENQ  */, 0 /* ACK  */, 0 /* BEL  */, 0 /* BS   */, 0 /* HT   */,
271     0 /* LF   */, 0 /* VT   */, 0 /* FF   */, 0 /* CR   */, 0 /* SO   */,
272     0 /* SI   */, 0 /* DLE  */, 0 /* DC1  */, 0 /* DC2  */, 0 /* DC3  */,
273     0 /* DC4  */, 0 /* NAK  */, 0 /* SYN  */, 0 /* ETB  */, 0 /* CAN  */,
274     0 /* EM   */, 0 /* SUB  */, 0 /* ESC  */, 0 /* FS   */, 0 /* GS   */,
275     0 /* RS   */, 0 /* US   */, 1 /* SPC  */, 1 /* !    */, 0 /* "    */,
276     1 /* #    */, 1 /* $    */, 1 /* %    */, 1 /* &    */, 1 /* '    */,
277     1 /* (    */, 1 /* )    */, 1 /* *    */, 1 /* +    */, 1 /* ,    */,
278     1 /* -    */, 1 /* .    */, 1 /* /    */, 1 /* 0    */, 1 /* 1    */,
279     1 /* 2    */, 1 /* 3    */, 1 /* 4    */, 1 /* 5    */, 1 /* 6    */,
280     1 /* 7    */, 1 /* 8    */, 1 /* 9    */, 1 /* :    */, 1 /* ;    */,
281     1 /* <    */, 1 /* =    */, 1 /* >    */, 1 /* ?    */, 1 /* @    */,
282     1 /* A    */, 1 /* B    */, 1 /* C    */, 1 /* D    */, 1 /* E    */,
283     1 /* F    */, 1 /* G    */, 1 /* H    */, 1 /* I    */, 1 /* J    */,
284     1 /* K    */, 1 /* L    */, 1 /* M    */, 1 /* N    */, 1 /* O    */,
285     1 /* P    */, 1 /* Q    */, 1 /* R    */, 1 /* S    */, 1 /* T    */,
286     1 /* U    */, 1 /* V    */, 1 /* W    */, 1 /* X    */, 1 /* Y    */,
287     1 /* Z    */, 1 /* [    */, 0 /* \    */, 1 /* ]    */, 1 /* ^    */,
288     1 /* _    */, 1 /* `    */, 1 /* a    */, 1 /* b    */, 1 /* c    */,
289     1 /* d    */, 1 /* e    */, 1 /* f    */, 1 /* g    */, 1 /* h    */,
290     1 /* i    */, 1 /* j    */, 1 /* k    */, 1 /* l    */, 1 /* m    */,
291     1 /* n    */, 1 /* o    */, 1 /* p    */, 1 /* q    */, 1 /* r    */,
292     1 /* s    */, 1 /* t    */, 1 /* u    */, 1 /* v    */, 1 /* w    */,
293     1 /* x    */, 1 /* y    */, 1 /* z    */, 1 /* {    */, 1 /* |    */,
294     1 /* }    */, 1 /* ~    */, 0 /* DEL  */, 0 /* 0x80 */, 0 /* 0x81 */,
295     0 /* 0x82 */, 0 /* 0x83 */, 0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */,
296     0 /* 0x87 */, 0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
297     0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */, 0 /* 0x90 */,
298     0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */, 0 /* 0x94 */, 0 /* 0x95 */,
299     0 /* 0x96 */, 0 /* 0x97 */, 0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */,
300     0 /* 0x9b */, 0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
301     0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */, 0 /* 0xa4 */,
302     0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */, 0 /* 0xa8 */, 0 /* 0xa9 */,
303     0 /* 0xaa */, 0 /* 0xab */, 0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */,
304     0 /* 0xaf */, 0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
305     0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */, 0 /* 0xb8 */,
306     0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */, 0 /* 0xbc */, 0 /* 0xbd */,
307     0 /* 0xbe */, 0 /* 0xbf */, 0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */,
308     0 /* 0xc3 */, 0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
309     0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */, 0 /* 0xcc */,
310     0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */, 0 /* 0xd0 */, 0 /* 0xd1 */,
311     0 /* 0xd2 */, 0 /* 0xd3 */, 0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */,
312     0 /* 0xd7 */, 0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
313     0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */, 0 /* 0xe0 */,
314     0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */, 0 /* 0xe4 */, 0 /* 0xe5 */,
315     0 /* 0xe6 */, 0 /* 0xe7 */, 0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */,
316     0 /* 0xeb */, 0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
317     0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */, 0 /* 0xf4 */,
318     0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */, 0 /* 0xf8 */, 0 /* 0xf9 */,
319     0 /* 0xfa */, 0 /* 0xfb */, 0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */,
320     0 /* 0xff */,
321 };
322 
sf_parse_string(nghttp3_sf_value * dest,const uint8_t * begin,const uint8_t * end)323 static nghttp3_ssize sf_parse_string(nghttp3_sf_value *dest,
324                                      const uint8_t *begin, const uint8_t *end) {
325   const uint8_t *p = begin;
326 
327   if (*p++ != '"') {
328     return -1;
329   }
330 
331   for (; p != end; ++p) {
332     switch (*p) {
333     case '\\':
334       if (++p == end) {
335         return -1;
336       }
337 
338       switch (*p) {
339       case '"':
340       case '\\':
341         break;
342       default:
343         return -1;
344       }
345 
346       break;
347     case '"':
348       if (dest) {
349         dest->type = NGHTTP3_SF_VALUE_TYPE_STRING;
350         dest->s.base = begin + 1;
351         dest->s.len = (size_t)(p - dest->s.base);
352       }
353 
354       ++p;
355 
356       return p - begin;
357     default:
358       if (!SF_DQUOTE_CHARS[*p]) {
359         return -1;
360       }
361     }
362   }
363 
364   return -1;
365 }
366 
367 /* Generated by genchartbl.py */
368 static const int SF_TOKEN_CHARS[] = {
369     0 /* NUL  */, 0 /* SOH  */, 0 /* STX  */, 0 /* ETX  */, 0 /* EOT  */,
370     0 /* ENQ  */, 0 /* ACK  */, 0 /* BEL  */, 0 /* BS   */, 0 /* HT   */,
371     0 /* LF   */, 0 /* VT   */, 0 /* FF   */, 0 /* CR   */, 0 /* SO   */,
372     0 /* SI   */, 0 /* DLE  */, 0 /* DC1  */, 0 /* DC2  */, 0 /* DC3  */,
373     0 /* DC4  */, 0 /* NAK  */, 0 /* SYN  */, 0 /* ETB  */, 0 /* CAN  */,
374     0 /* EM   */, 0 /* SUB  */, 0 /* ESC  */, 0 /* FS   */, 0 /* GS   */,
375     0 /* RS   */, 0 /* US   */, 0 /* SPC  */, 1 /* !    */, 0 /* "    */,
376     1 /* #    */, 1 /* $    */, 1 /* %    */, 1 /* &    */, 1 /* '    */,
377     0 /* (    */, 0 /* )    */, 1 /* *    */, 1 /* +    */, 0 /* ,    */,
378     1 /* -    */, 1 /* .    */, 1 /* /    */, 1 /* 0    */, 1 /* 1    */,
379     1 /* 2    */, 1 /* 3    */, 1 /* 4    */, 1 /* 5    */, 1 /* 6    */,
380     1 /* 7    */, 1 /* 8    */, 1 /* 9    */, 1 /* :    */, 0 /* ;    */,
381     0 /* <    */, 0 /* =    */, 0 /* >    */, 0 /* ?    */, 0 /* @    */,
382     1 /* A    */, 1 /* B    */, 1 /* C    */, 1 /* D    */, 1 /* E    */,
383     1 /* F    */, 1 /* G    */, 1 /* H    */, 1 /* I    */, 1 /* J    */,
384     1 /* K    */, 1 /* L    */, 1 /* M    */, 1 /* N    */, 1 /* O    */,
385     1 /* P    */, 1 /* Q    */, 1 /* R    */, 1 /* S    */, 1 /* T    */,
386     1 /* U    */, 1 /* V    */, 1 /* W    */, 1 /* X    */, 1 /* Y    */,
387     1 /* Z    */, 0 /* [    */, 0 /* \    */, 0 /* ]    */, 1 /* ^    */,
388     1 /* _    */, 1 /* `    */, 1 /* a    */, 1 /* b    */, 1 /* c    */,
389     1 /* d    */, 1 /* e    */, 1 /* f    */, 1 /* g    */, 1 /* h    */,
390     1 /* i    */, 1 /* j    */, 1 /* k    */, 1 /* l    */, 1 /* m    */,
391     1 /* n    */, 1 /* o    */, 1 /* p    */, 1 /* q    */, 1 /* r    */,
392     1 /* s    */, 1 /* t    */, 1 /* u    */, 1 /* v    */, 1 /* w    */,
393     1 /* x    */, 1 /* y    */, 1 /* z    */, 0 /* {    */, 1 /* |    */,
394     0 /* }    */, 1 /* ~    */, 0 /* DEL  */, 0 /* 0x80 */, 0 /* 0x81 */,
395     0 /* 0x82 */, 0 /* 0x83 */, 0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */,
396     0 /* 0x87 */, 0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
397     0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */, 0 /* 0x90 */,
398     0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */, 0 /* 0x94 */, 0 /* 0x95 */,
399     0 /* 0x96 */, 0 /* 0x97 */, 0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */,
400     0 /* 0x9b */, 0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
401     0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */, 0 /* 0xa4 */,
402     0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */, 0 /* 0xa8 */, 0 /* 0xa9 */,
403     0 /* 0xaa */, 0 /* 0xab */, 0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */,
404     0 /* 0xaf */, 0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
405     0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */, 0 /* 0xb8 */,
406     0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */, 0 /* 0xbc */, 0 /* 0xbd */,
407     0 /* 0xbe */, 0 /* 0xbf */, 0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */,
408     0 /* 0xc3 */, 0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
409     0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */, 0 /* 0xcc */,
410     0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */, 0 /* 0xd0 */, 0 /* 0xd1 */,
411     0 /* 0xd2 */, 0 /* 0xd3 */, 0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */,
412     0 /* 0xd7 */, 0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
413     0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */, 0 /* 0xe0 */,
414     0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */, 0 /* 0xe4 */, 0 /* 0xe5 */,
415     0 /* 0xe6 */, 0 /* 0xe7 */, 0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */,
416     0 /* 0xeb */, 0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
417     0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */, 0 /* 0xf4 */,
418     0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */, 0 /* 0xf8 */, 0 /* 0xf9 */,
419     0 /* 0xfa */, 0 /* 0xfb */, 0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */,
420     0 /* 0xff */,
421 };
422 
sf_parse_token(nghttp3_sf_value * dest,const uint8_t * begin,const uint8_t * end)423 static nghttp3_ssize sf_parse_token(nghttp3_sf_value *dest,
424                                     const uint8_t *begin, const uint8_t *end) {
425   const uint8_t *p = begin;
426 
427   if ((*p < 'A' || 'Z' < *p) && (*p < 'a' || 'z' < *p) && *p != '*') {
428     return -1;
429   }
430 
431   for (; p != end && SF_TOKEN_CHARS[*p]; ++p)
432     ;
433 
434   if (dest) {
435     dest->type = NGHTTP3_SF_VALUE_TYPE_TOKEN;
436     dest->s.base = begin;
437     dest->s.len = (size_t)(p - begin);
438   }
439 
440   return p - begin;
441 }
442 
443 /* Generated by genchartbl.py */
444 static const int SF_BYTESEQ_CHARS[] = {
445     0 /* NUL  */, 0 /* SOH  */, 0 /* STX  */, 0 /* ETX  */, 0 /* EOT  */,
446     0 /* ENQ  */, 0 /* ACK  */, 0 /* BEL  */, 0 /* BS   */, 0 /* HT   */,
447     0 /* LF   */, 0 /* VT   */, 0 /* FF   */, 0 /* CR   */, 0 /* SO   */,
448     0 /* SI   */, 0 /* DLE  */, 0 /* DC1  */, 0 /* DC2  */, 0 /* DC3  */,
449     0 /* DC4  */, 0 /* NAK  */, 0 /* SYN  */, 0 /* ETB  */, 0 /* CAN  */,
450     0 /* EM   */, 0 /* SUB  */, 0 /* ESC  */, 0 /* FS   */, 0 /* GS   */,
451     0 /* RS   */, 0 /* US   */, 0 /* SPC  */, 0 /* !    */, 0 /* "    */,
452     0 /* #    */, 0 /* $    */, 0 /* %    */, 0 /* &    */, 0 /* '    */,
453     0 /* (    */, 0 /* )    */, 0 /* *    */, 1 /* +    */, 0 /* ,    */,
454     0 /* -    */, 0 /* .    */, 1 /* /    */, 1 /* 0    */, 1 /* 1    */,
455     1 /* 2    */, 1 /* 3    */, 1 /* 4    */, 1 /* 5    */, 1 /* 6    */,
456     1 /* 7    */, 1 /* 8    */, 1 /* 9    */, 0 /* :    */, 0 /* ;    */,
457     0 /* <    */, 1 /* =    */, 0 /* >    */, 0 /* ?    */, 0 /* @    */,
458     1 /* A    */, 1 /* B    */, 1 /* C    */, 1 /* D    */, 1 /* E    */,
459     1 /* F    */, 1 /* G    */, 1 /* H    */, 1 /* I    */, 1 /* J    */,
460     1 /* K    */, 1 /* L    */, 1 /* M    */, 1 /* N    */, 1 /* O    */,
461     1 /* P    */, 1 /* Q    */, 1 /* R    */, 1 /* S    */, 1 /* T    */,
462     1 /* U    */, 1 /* V    */, 1 /* W    */, 1 /* X    */, 1 /* Y    */,
463     1 /* Z    */, 0 /* [    */, 0 /* \    */, 0 /* ]    */, 0 /* ^    */,
464     0 /* _    */, 0 /* `    */, 1 /* a    */, 1 /* b    */, 1 /* c    */,
465     1 /* d    */, 1 /* e    */, 1 /* f    */, 1 /* g    */, 1 /* h    */,
466     1 /* i    */, 1 /* j    */, 1 /* k    */, 1 /* l    */, 1 /* m    */,
467     1 /* n    */, 1 /* o    */, 1 /* p    */, 1 /* q    */, 1 /* r    */,
468     1 /* s    */, 1 /* t    */, 1 /* u    */, 1 /* v    */, 1 /* w    */,
469     1 /* x    */, 1 /* y    */, 1 /* z    */, 0 /* {    */, 0 /* |    */,
470     0 /* }    */, 0 /* ~    */, 0 /* DEL  */, 0 /* 0x80 */, 0 /* 0x81 */,
471     0 /* 0x82 */, 0 /* 0x83 */, 0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */,
472     0 /* 0x87 */, 0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
473     0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */, 0 /* 0x90 */,
474     0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */, 0 /* 0x94 */, 0 /* 0x95 */,
475     0 /* 0x96 */, 0 /* 0x97 */, 0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */,
476     0 /* 0x9b */, 0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
477     0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */, 0 /* 0xa4 */,
478     0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */, 0 /* 0xa8 */, 0 /* 0xa9 */,
479     0 /* 0xaa */, 0 /* 0xab */, 0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */,
480     0 /* 0xaf */, 0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
481     0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */, 0 /* 0xb8 */,
482     0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */, 0 /* 0xbc */, 0 /* 0xbd */,
483     0 /* 0xbe */, 0 /* 0xbf */, 0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */,
484     0 /* 0xc3 */, 0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
485     0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */, 0 /* 0xcc */,
486     0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */, 0 /* 0xd0 */, 0 /* 0xd1 */,
487     0 /* 0xd2 */, 0 /* 0xd3 */, 0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */,
488     0 /* 0xd7 */, 0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
489     0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */, 0 /* 0xe0 */,
490     0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */, 0 /* 0xe4 */, 0 /* 0xe5 */,
491     0 /* 0xe6 */, 0 /* 0xe7 */, 0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */,
492     0 /* 0xeb */, 0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
493     0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */, 0 /* 0xf4 */,
494     0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */, 0 /* 0xf8 */, 0 /* 0xf9 */,
495     0 /* 0xfa */, 0 /* 0xfb */, 0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */,
496     0 /* 0xff */,
497 };
498 
sf_parse_byteseq(nghttp3_sf_value * dest,const uint8_t * begin,const uint8_t * end)499 static nghttp3_ssize sf_parse_byteseq(nghttp3_sf_value *dest,
500                                       const uint8_t *begin,
501                                       const uint8_t *end) {
502   const uint8_t *p = begin;
503 
504   if (*p++ != ':') {
505     return -1;
506   }
507 
508   for (; p != end; ++p) {
509     switch (*p) {
510     case ':':
511       if (dest) {
512         dest->type = NGHTTP3_SF_VALUE_TYPE_BYTESEQ;
513         dest->s.base = begin + 1;
514         dest->s.len = (size_t)(p - dest->s.base);
515       }
516 
517       ++p;
518 
519       return p - begin;
520     default:
521       if (!SF_BYTESEQ_CHARS[*p]) {
522         return -1;
523       }
524     }
525   }
526 
527   return -1;
528 }
529 
sf_parse_boolean(nghttp3_sf_value * dest,const uint8_t * begin,const uint8_t * end)530 static nghttp3_ssize sf_parse_boolean(nghttp3_sf_value *dest,
531                                       const uint8_t *begin,
532                                       const uint8_t *end) {
533   const uint8_t *p = begin;
534   int b;
535 
536   if (*p++ != '?') {
537     return -1;
538   }
539 
540   if (p == end) {
541     return -1;
542   }
543 
544   switch (*p++) {
545   case '0':
546     b = 0;
547     break;
548   case '1':
549     b = 1;
550     break;
551   default:
552     return -1;
553   }
554 
555   if (dest) {
556     dest->type = NGHTTP3_SF_VALUE_TYPE_BOOLEAN;
557     dest->b = b;
558   }
559 
560   return p - begin;
561 }
562 
sf_parse_bare_item(nghttp3_sf_value * dest,const uint8_t * begin,const uint8_t * end)563 static nghttp3_ssize sf_parse_bare_item(nghttp3_sf_value *dest,
564                                         const uint8_t *begin,
565                                         const uint8_t *end) {
566   switch (*begin) {
567   case '-':
568   case '0':
569   case '1':
570   case '2':
571   case '3':
572   case '4':
573   case '5':
574   case '6':
575   case '7':
576   case '8':
577   case '9':
578     return sf_parse_integer_or_decimal(dest, begin, end);
579   case '"':
580     return sf_parse_string(dest, begin, end);
581   case '*':
582     return sf_parse_token(dest, begin, end);
583   case ':':
584     return sf_parse_byteseq(dest, begin, end);
585   case '?':
586     return sf_parse_boolean(dest, begin, end);
587   default:
588     if (('A' <= *begin && *begin <= 'Z') || ('a' <= *begin && *begin <= 'z')) {
589       return sf_parse_token(dest, begin, end);
590     }
591     return -1;
592   }
593 }
594 
595 #define sf_discard_sp_end_err(BEGIN, END, ERR)                                 \
596   for (;; ++(BEGIN)) {                                                         \
597     if ((BEGIN) == (END)) {                                                    \
598       return (ERR);                                                            \
599     }                                                                          \
600     if (*(BEGIN) != ' ') {                                                     \
601       break;                                                                   \
602     }                                                                          \
603   }
604 
sf_parse_params(const uint8_t * begin,const uint8_t * end)605 static nghttp3_ssize sf_parse_params(const uint8_t *begin, const uint8_t *end) {
606   const uint8_t *p = begin;
607   nghttp3_ssize slen;
608 
609   for (; p != end && *p == ';';) {
610     ++p;
611 
612     sf_discard_sp_end_err(p, end, -1);
613 
614     slen = sf_parse_key(p, end);
615     if (slen < 0) {
616       return -1;
617     }
618 
619     p += slen;
620 
621     if (p == end || *p != '=') {
622       /* Boolean true */
623     } else if (++p == end) {
624       return -1;
625     } else {
626       slen = sf_parse_bare_item(NULL, p, end);
627       if (slen < 0) {
628         return -1;
629       }
630 
631       p += slen;
632     }
633   }
634 
635   return p - begin;
636 }
637 
sf_parse_item(nghttp3_sf_value * dest,const uint8_t * begin,const uint8_t * end)638 static nghttp3_ssize sf_parse_item(nghttp3_sf_value *dest, const uint8_t *begin,
639                                    const uint8_t *end) {
640   const uint8_t *p = begin;
641   nghttp3_ssize slen;
642 
643   slen = sf_parse_bare_item(dest, p, end);
644   if (slen < 0) {
645     return -1;
646   }
647 
648   p += slen;
649 
650   slen = sf_parse_params(p, end);
651   if (slen < 0) {
652     return -1;
653   }
654 
655   p += slen;
656 
657   return p - begin;
658 }
659 
nghttp3_sf_parse_item(nghttp3_sf_value * dest,const uint8_t * begin,const uint8_t * end)660 nghttp3_ssize nghttp3_sf_parse_item(nghttp3_sf_value *dest,
661                                     const uint8_t *begin, const uint8_t *end) {
662   return sf_parse_item(dest, begin, end);
663 }
664 
sf_parse_inner_list(nghttp3_sf_value * dest,const uint8_t * begin,const uint8_t * end)665 static nghttp3_ssize sf_parse_inner_list(nghttp3_sf_value *dest,
666                                          const uint8_t *begin,
667                                          const uint8_t *end) {
668   const uint8_t *p = begin;
669   nghttp3_ssize slen;
670 
671   if (*p++ != '(') {
672     return -1;
673   }
674 
675   for (;;) {
676     sf_discard_sp_end_err(p, end, -1);
677 
678     if (*p == ')') {
679       ++p;
680 
681       slen = sf_parse_params(p, end);
682       if (slen < 0) {
683         return -1;
684       }
685 
686       p += slen;
687 
688       if (dest) {
689         dest->type = NGHTTP3_SF_VALUE_TYPE_INNER_LIST;
690       }
691 
692       return p - begin;
693     }
694 
695     slen = sf_parse_item(NULL, p, end);
696     if (slen < 0) {
697       return -1;
698     }
699 
700     p += slen;
701 
702     if (p == end || (*p != ' ' && *p != ')')) {
703       return -1;
704     }
705   }
706 }
707 
nghttp3_sf_parse_inner_list(nghttp3_sf_value * dest,const uint8_t * begin,const uint8_t * end)708 nghttp3_ssize nghttp3_sf_parse_inner_list(nghttp3_sf_value *dest,
709                                           const uint8_t *begin,
710                                           const uint8_t *end) {
711   return sf_parse_inner_list(dest, begin, end);
712 }
713 
sf_parse_item_or_inner_list(nghttp3_sf_value * dest,const uint8_t * begin,const uint8_t * end)714 static nghttp3_ssize sf_parse_item_or_inner_list(nghttp3_sf_value *dest,
715                                                  const uint8_t *begin,
716                                                  const uint8_t *end) {
717   if (*begin == '(') {
718     return sf_parse_inner_list(dest, begin, end);
719   }
720 
721   return sf_parse_item(dest, begin, end);
722 }
723 
724 #define sf_discard_ows(BEGIN, END)                                             \
725   for (;; ++(BEGIN)) {                                                         \
726     if ((BEGIN) == (END)) {                                                    \
727       goto fin;                                                                \
728     }                                                                          \
729     if (*(BEGIN) != ' ' && *(BEGIN) != '\t') {                                 \
730       break;                                                                   \
731     }                                                                          \
732   }
733 
734 #define sf_discard_ows_end_err(BEGIN, END, ERR)                                \
735   for (;; ++(BEGIN)) {                                                         \
736     if ((BEGIN) == (END)) {                                                    \
737       return (ERR);                                                            \
738     }                                                                          \
739     if (*(BEGIN) != ' ' && *(BEGIN) != '\t') {                                 \
740       break;                                                                   \
741     }                                                                          \
742   }
743 
nghttp3_http_parse_priority(nghttp3_pri * dest,const uint8_t * value,size_t valuelen)744 int nghttp3_http_parse_priority(nghttp3_pri *dest, const uint8_t *value,
745                                 size_t valuelen) {
746   const uint8_t *p = value, *end = value + valuelen;
747   nghttp3_ssize slen;
748   nghttp3_sf_value val;
749   nghttp3_pri pri = *dest;
750   const uint8_t *key;
751   size_t keylen;
752 
753   for (; p != end && *p == ' '; ++p)
754     ;
755 
756   for (; p != end;) {
757     slen = sf_parse_key(p, end);
758     if (slen < 0) {
759       return NGHTTP3_ERR_INVALID_ARGUMENT;
760     }
761 
762     key = p;
763     keylen = (size_t)slen;
764 
765     p += slen;
766 
767     if (p == end || *p != '=') {
768       /* Boolean true */
769       val.type = NGHTTP3_SF_VALUE_TYPE_BOOLEAN;
770       val.b = 1;
771 
772       slen = sf_parse_params(p, end);
773       if (slen < 0) {
774         return NGHTTP3_ERR_INVALID_ARGUMENT;
775       }
776     } else if (++p == end) {
777       return NGHTTP3_ERR_INVALID_ARGUMENT;
778     } else {
779       slen = sf_parse_item_or_inner_list(&val, p, end);
780       if (slen < 0) {
781         return NGHTTP3_ERR_INVALID_ARGUMENT;
782       }
783     }
784 
785     p += slen;
786 
787     if (keylen == 1) {
788       switch (key[0]) {
789       case 'i':
790         if (val.type != NGHTTP3_SF_VALUE_TYPE_BOOLEAN) {
791           return NGHTTP3_ERR_INVALID_ARGUMENT;
792         }
793 
794         pri.inc = val.b;
795 
796         break;
797       case 'u':
798         if (val.type != NGHTTP3_SF_VALUE_TYPE_INTEGER ||
799             val.i < NGHTTP3_URGENCY_HIGH || NGHTTP3_URGENCY_LOW < val.i) {
800           return NGHTTP3_ERR_INVALID_ARGUMENT;
801         }
802 
803         pri.urgency = (uint32_t)val.i;
804 
805         break;
806       }
807     }
808 
809     sf_discard_ows(p, end);
810 
811     if (*p++ != ',') {
812       return NGHTTP3_ERR_INVALID_ARGUMENT;
813     }
814 
815     sf_discard_ows_end_err(p, end, NGHTTP3_ERR_INVALID_ARGUMENT);
816   }
817 
818 fin:
819   *dest = pri;
820 
821   return 0;
822 }
823 
http_request_on_header(nghttp3_http_state * http,nghttp3_qpack_nv * nv,int trailers,int connect_protocol)824 static int http_request_on_header(nghttp3_http_state *http,
825                                   nghttp3_qpack_nv *nv, int trailers,
826                                   int connect_protocol) {
827   nghttp3_pri pri;
828 
829   if (nv->name->base[0] == ':') {
830     if (trailers ||
831         (http->flags & NGHTTP3_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED)) {
832       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
833     }
834   }
835 
836   switch (nv->token) {
837   case NGHTTP3_QPACK_TOKEN__AUTHORITY:
838     if (!check_pseudo_header(http, nv, NGHTTP3_HTTP_FLAG__AUTHORITY)) {
839       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
840     }
841     break;
842   case NGHTTP3_QPACK_TOKEN__METHOD:
843     if (!check_pseudo_header(http, nv, NGHTTP3_HTTP_FLAG__METHOD)) {
844       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
845     }
846     switch (nv->value->len) {
847     case 4:
848       if (lstreq("HEAD", nv->value->base, nv->value->len)) {
849         http->flags |= NGHTTP3_HTTP_FLAG_METH_HEAD;
850       }
851       break;
852     case 7:
853       switch (nv->value->base[6]) {
854       case 'T':
855         if (lstreq("CONNECT", nv->value->base, nv->value->len)) {
856           http->flags |= NGHTTP3_HTTP_FLAG_METH_CONNECT;
857         }
858         break;
859       case 'S':
860         if (lstreq("OPTIONS", nv->value->base, nv->value->len)) {
861           http->flags |= NGHTTP3_HTTP_FLAG_METH_OPTIONS;
862         }
863         break;
864       }
865       break;
866     }
867     break;
868   case NGHTTP3_QPACK_TOKEN__PATH:
869     if (!check_pseudo_header(http, nv, NGHTTP3_HTTP_FLAG__PATH)) {
870       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
871     }
872     if (nv->value->base[0] == '/') {
873       http->flags |= NGHTTP3_HTTP_FLAG_PATH_REGULAR;
874     } else if (nv->value->len == 1 && nv->value->base[0] == '*') {
875       http->flags |= NGHTTP3_HTTP_FLAG_PATH_ASTERISK;
876     }
877     break;
878   case NGHTTP3_QPACK_TOKEN__SCHEME:
879     if (!check_pseudo_header(http, nv, NGHTTP3_HTTP_FLAG__SCHEME)) {
880       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
881     }
882     /* scheme is case-insensitive:
883        https://datatracker.ietf.org/doc/html/rfc3986#section-3.1 */
884     if (lstrieq("http", nv->value->base, nv->value->len) ||
885         lstrieq("https", nv->value->base, nv->value->len)) {
886       http->flags |= NGHTTP3_HTTP_FLAG_SCHEME_HTTP;
887     }
888     break;
889   case NGHTTP3_QPACK_TOKEN__PROTOCOL:
890     if (!connect_protocol) {
891       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
892     }
893 
894     if (!check_pseudo_header(http, nv, NGHTTP3_HTTP_FLAG__PROTOCOL)) {
895       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
896     }
897     break;
898   case NGHTTP3_QPACK_TOKEN_HOST:
899     if (!check_pseudo_header(http, nv, NGHTTP3_HTTP_FLAG_HOST)) {
900       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
901     }
902     break;
903   case NGHTTP3_QPACK_TOKEN_CONTENT_LENGTH: {
904     /* https://tools.ietf.org/html/rfc7230#section-4.1.2: A sender
905        MUST NOT generate a trailer that contains a field necessary for
906        message framing (e.g., Transfer-Encoding and Content-Length),
907        ... */
908     if (trailers) {
909       return NGHTTP3_ERR_REMOVE_HTTP_HEADER;
910     }
911     if (http->content_length != -1) {
912       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
913     }
914     http->content_length = parse_uint(nv->value->base, nv->value->len);
915     if (http->content_length == -1) {
916       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
917     }
918     break;
919   }
920   /* disallowed header fields */
921   case NGHTTP3_QPACK_TOKEN_CONNECTION:
922   case NGHTTP3_QPACK_TOKEN_KEEP_ALIVE:
923   case NGHTTP3_QPACK_TOKEN_PROXY_CONNECTION:
924   case NGHTTP3_QPACK_TOKEN_TRANSFER_ENCODING:
925   case NGHTTP3_QPACK_TOKEN_UPGRADE:
926     return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
927   case NGHTTP3_QPACK_TOKEN_TE:
928     if (!lstrieq("trailers", nv->value->base, nv->value->len)) {
929       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
930     }
931     break;
932   case NGHTTP3_QPACK_TOKEN_PRIORITY:
933     if (!trailers && !(http->flags & NGHTTP3_HTTP_FLAG_BAD_PRIORITY)) {
934       pri.urgency = nghttp3_pri_uint8_urgency(http->pri);
935       pri.inc = nghttp3_pri_uint8_inc(http->pri);
936       if (nghttp3_http_parse_priority(&pri, nv->value->base, nv->value->len) ==
937           0) {
938         http->pri = nghttp3_pri_to_uint8(&pri);
939         http->flags |= NGHTTP3_HTTP_FLAG_PRIORITY;
940       } else {
941         http->flags &= ~NGHTTP3_HTTP_FLAG_PRIORITY;
942         http->flags |= NGHTTP3_HTTP_FLAG_BAD_PRIORITY;
943       }
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     if (request) {
1335       rv = check_authority(nv->value->base, nv->value->len);
1336     } else {
1337       /* The use of host field in response field section is
1338          undefined. */
1339       rv = nghttp3_check_header_value(nv->value->base, nv->value->len);
1340     }
1341     break;
1342   case NGHTTP3_QPACK_TOKEN__PATH:
1343     rv = check_path(nv->value->base, nv->value->len);
1344     break;
1345   default:
1346     rv = nghttp3_check_header_value(nv->value->base, nv->value->len);
1347   }
1348 
1349   if (rv == 0) {
1350     if (nv->name->base[0] == ':') {
1351       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
1352     }
1353     /* When ignoring regular header fields, we set this flag so that
1354        we still enforce header field ordering rule for pseudo header
1355        fields. */
1356     http->flags |= NGHTTP3_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED;
1357     return NGHTTP3_ERR_REMOVE_HTTP_HEADER;
1358   }
1359 
1360   if (request) {
1361     rv = http_request_on_header(http, nv, trailers, connect_protocol);
1362   } else {
1363     rv = http_response_on_header(http, nv, trailers);
1364   }
1365 
1366   if (nv->name->base[0] != ':') {
1367     switch (rv) {
1368     case 0:
1369     case NGHTTP3_ERR_REMOVE_HTTP_HEADER:
1370       http->flags |= NGHTTP3_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED;
1371       break;
1372     }
1373   }
1374 
1375   return rv;
1376 }
1377 
nghttp3_http_on_request_headers(nghttp3_http_state * http)1378 int nghttp3_http_on_request_headers(nghttp3_http_state *http) {
1379   if (!(http->flags & NGHTTP3_HTTP_FLAG__PROTOCOL) &&
1380       (http->flags & NGHTTP3_HTTP_FLAG_METH_CONNECT)) {
1381     if ((http->flags & (NGHTTP3_HTTP_FLAG__SCHEME | NGHTTP3_HTTP_FLAG__PATH)) ||
1382         (http->flags & NGHTTP3_HTTP_FLAG__AUTHORITY) == 0) {
1383       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
1384     }
1385     http->content_length = -1;
1386   } else {
1387     if ((http->flags & NGHTTP3_HTTP_FLAG_REQ_HEADERS) !=
1388             NGHTTP3_HTTP_FLAG_REQ_HEADERS ||
1389         (http->flags &
1390          (NGHTTP3_HTTP_FLAG__AUTHORITY | NGHTTP3_HTTP_FLAG_HOST)) == 0) {
1391       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
1392     }
1393     if ((http->flags & NGHTTP3_HTTP_FLAG__PROTOCOL) &&
1394         ((http->flags & NGHTTP3_HTTP_FLAG_METH_CONNECT) == 0 ||
1395          (http->flags & NGHTTP3_HTTP_FLAG__AUTHORITY) == 0)) {
1396       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
1397     }
1398     if (!check_path_flags(http)) {
1399       return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
1400     }
1401   }
1402 
1403   return 0;
1404 }
1405 
nghttp3_http_on_response_headers(nghttp3_http_state * http)1406 int nghttp3_http_on_response_headers(nghttp3_http_state *http) {
1407   if ((http->flags & NGHTTP3_HTTP_FLAG__STATUS) == 0) {
1408     return NGHTTP3_ERR_MALFORMED_HTTP_HEADER;
1409   }
1410 
1411   if (http->status_code / 100 == 1) {
1412     /* non-final response */
1413     http->flags = (http->flags & NGHTTP3_HTTP_FLAG_METH_ALL) |
1414                   NGHTTP3_HTTP_FLAG_EXPECT_FINAL_RESPONSE;
1415     http->content_length = -1;
1416     http->status_code = -1;
1417     return 0;
1418   }
1419 
1420   http->flags &= ~NGHTTP3_HTTP_FLAG_EXPECT_FINAL_RESPONSE;
1421 
1422   if (!expect_response_body(http)) {
1423     http->content_length = 0;
1424   } else if (http->flags & NGHTTP3_HTTP_FLAG_METH_CONNECT) {
1425     http->content_length = -1;
1426   }
1427 
1428   return 0;
1429 }
1430 
nghttp3_http_on_remote_end_stream(nghttp3_stream * stream)1431 int nghttp3_http_on_remote_end_stream(nghttp3_stream *stream) {
1432   if ((stream->rx.http.flags & NGHTTP3_HTTP_FLAG_EXPECT_FINAL_RESPONSE) ||
1433       (stream->rx.http.content_length != -1 &&
1434        stream->rx.http.content_length != stream->rx.http.recv_content_length)) {
1435     return NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING;
1436   }
1437 
1438   return 0;
1439 }
1440 
nghttp3_http_on_data_chunk(nghttp3_stream * stream,size_t n)1441 int nghttp3_http_on_data_chunk(nghttp3_stream *stream, size_t n) {
1442   stream->rx.http.recv_content_length += (int64_t)n;
1443 
1444   if ((stream->rx.http.flags & NGHTTP3_HTTP_FLAG_EXPECT_FINAL_RESPONSE) ||
1445       (stream->rx.http.content_length != -1 &&
1446        stream->rx.http.recv_content_length > stream->rx.http.content_length)) {
1447     return NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING;
1448   }
1449 
1450   return 0;
1451 }
1452 
nghttp3_http_record_request_method(nghttp3_stream * stream,const nghttp3_nv * nva,size_t nvlen)1453 void nghttp3_http_record_request_method(nghttp3_stream *stream,
1454                                         const nghttp3_nv *nva, size_t nvlen) {
1455   size_t i;
1456   const nghttp3_nv *nv;
1457 
1458   /* TODO we should do this strictly. */
1459   for (i = 0; i < nvlen; ++i) {
1460     nv = &nva[i];
1461     if (!(nv->namelen == 7 && nv->name[6] == 'd' &&
1462           memcmp(":metho", nv->name, nv->namelen - 1) == 0)) {
1463       continue;
1464     }
1465     if (lstreq("CONNECT", nv->value, nv->valuelen)) {
1466       stream->rx.http.flags |= NGHTTP3_HTTP_FLAG_METH_CONNECT;
1467       return;
1468     }
1469     if (lstreq("HEAD", nv->value, nv->valuelen)) {
1470       stream->rx.http.flags |= NGHTTP3_HTTP_FLAG_METH_HEAD;
1471       return;
1472     }
1473     return;
1474   }
1475 }
1476 
1477 /* Generated by gennmchartbl.py */
1478 static const int VALID_HD_NAME_CHARS[] = {
1479     0 /* NUL  */, 0 /* SOH  */, 0 /* STX  */, 0 /* ETX  */,
1480     0 /* EOT  */, 0 /* ENQ  */, 0 /* ACK  */, 0 /* BEL  */,
1481     0 /* BS   */, 0 /* HT   */, 0 /* LF   */, 0 /* VT   */,
1482     0 /* FF   */, 0 /* CR   */, 0 /* SO   */, 0 /* SI   */,
1483     0 /* DLE  */, 0 /* DC1  */, 0 /* DC2  */, 0 /* DC3  */,
1484     0 /* DC4  */, 0 /* NAK  */, 0 /* SYN  */, 0 /* ETB  */,
1485     0 /* CAN  */, 0 /* EM   */, 0 /* SUB  */, 0 /* ESC  */,
1486     0 /* FS   */, 0 /* GS   */, 0 /* RS   */, 0 /* US   */,
1487     0 /* SPC  */, 1 /* !    */, 0 /* "    */, 1 /* #    */,
1488     1 /* $    */, 1 /* %    */, 1 /* &    */, 1 /* '    */,
1489     0 /* (    */, 0 /* )    */, 1 /* *    */, 1 /* +    */,
1490     0 /* ,    */, 1 /* -    */, 1 /* .    */, 0 /* /    */,
1491     1 /* 0    */, 1 /* 1    */, 1 /* 2    */, 1 /* 3    */,
1492     1 /* 4    */, 1 /* 5    */, 1 /* 6    */, 1 /* 7    */,
1493     1 /* 8    */, 1 /* 9    */, 0 /* :    */, 0 /* ;    */,
1494     0 /* <    */, 0 /* =    */, 0 /* >    */, 0 /* ?    */,
1495     0 /* @    */, 0 /* A    */, 0 /* B    */, 0 /* C    */,
1496     0 /* D    */, 0 /* E    */, 0 /* F    */, 0 /* G    */,
1497     0 /* H    */, 0 /* I    */, 0 /* J    */, 0 /* K    */,
1498     0 /* L    */, 0 /* M    */, 0 /* N    */, 0 /* O    */,
1499     0 /* P    */, 0 /* Q    */, 0 /* R    */, 0 /* S    */,
1500     0 /* T    */, 0 /* U    */, 0 /* V    */, 0 /* W    */,
1501     0 /* X    */, 0 /* Y    */, 0 /* Z    */, 0 /* [    */,
1502     0 /* \    */, 0 /* ]    */, 1 /* ^    */, 1 /* _    */,
1503     1 /* `    */, 1 /* a    */, 1 /* b    */, 1 /* c    */,
1504     1 /* d    */, 1 /* e    */, 1 /* f    */, 1 /* g    */,
1505     1 /* h    */, 1 /* i    */, 1 /* j    */, 1 /* k    */,
1506     1 /* l    */, 1 /* m    */, 1 /* n    */, 1 /* o    */,
1507     1 /* p    */, 1 /* q    */, 1 /* r    */, 1 /* s    */,
1508     1 /* t    */, 1 /* u    */, 1 /* v    */, 1 /* w    */,
1509     1 /* x    */, 1 /* y    */, 1 /* z    */, 0 /* {    */,
1510     1 /* |    */, 0 /* }    */, 1 /* ~    */, 0 /* DEL  */,
1511     0 /* 0x80 */, 0 /* 0x81 */, 0 /* 0x82 */, 0 /* 0x83 */,
1512     0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, 0 /* 0x87 */,
1513     0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
1514     0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */,
1515     0 /* 0x90 */, 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */,
1516     0 /* 0x94 */, 0 /* 0x95 */, 0 /* 0x96 */, 0 /* 0x97 */,
1517     0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, 0 /* 0x9b */,
1518     0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
1519     0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */,
1520     0 /* 0xa4 */, 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */,
1521     0 /* 0xa8 */, 0 /* 0xa9 */, 0 /* 0xaa */, 0 /* 0xab */,
1522     0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, 0 /* 0xaf */,
1523     0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
1524     0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */,
1525     0 /* 0xb8 */, 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */,
1526     0 /* 0xbc */, 0 /* 0xbd */, 0 /* 0xbe */, 0 /* 0xbf */,
1527     0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, 0 /* 0xc3 */,
1528     0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
1529     0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */,
1530     0 /* 0xcc */, 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */,
1531     0 /* 0xd0 */, 0 /* 0xd1 */, 0 /* 0xd2 */, 0 /* 0xd3 */,
1532     0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, 0 /* 0xd7 */,
1533     0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
1534     0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */,
1535     0 /* 0xe0 */, 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */,
1536     0 /* 0xe4 */, 0 /* 0xe5 */, 0 /* 0xe6 */, 0 /* 0xe7 */,
1537     0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, 0 /* 0xeb */,
1538     0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
1539     0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */,
1540     0 /* 0xf4 */, 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */,
1541     0 /* 0xf8 */, 0 /* 0xf9 */, 0 /* 0xfa */, 0 /* 0xfb */,
1542     0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, 0 /* 0xff */
1543 };
1544 
nghttp3_check_header_name(const uint8_t * name,size_t len)1545 int nghttp3_check_header_name(const uint8_t *name, size_t len) {
1546   const uint8_t *last;
1547   if (len == 0) {
1548     return 0;
1549   }
1550   if (*name == ':') {
1551     if (len == 1) {
1552       return 0;
1553     }
1554     ++name;
1555     --len;
1556   }
1557   for (last = name + len; name != last; ++name) {
1558     if (!VALID_HD_NAME_CHARS[*name]) {
1559       return 0;
1560     }
1561   }
1562   return 1;
1563 }
1564 
1565 /* Generated by genvchartbl.py */
1566 static const int VALID_HD_VALUE_CHARS[] = {
1567     0 /* NUL  */, 0 /* SOH  */, 0 /* STX  */, 0 /* ETX  */,
1568     0 /* EOT  */, 0 /* ENQ  */, 0 /* ACK  */, 0 /* BEL  */,
1569     0 /* BS   */, 1 /* HT   */, 0 /* LF   */, 0 /* VT   */,
1570     0 /* FF   */, 0 /* CR   */, 0 /* SO   */, 0 /* SI   */,
1571     0 /* DLE  */, 0 /* DC1  */, 0 /* DC2  */, 0 /* DC3  */,
1572     0 /* DC4  */, 0 /* NAK  */, 0 /* SYN  */, 0 /* ETB  */,
1573     0 /* CAN  */, 0 /* EM   */, 0 /* SUB  */, 0 /* ESC  */,
1574     0 /* FS   */, 0 /* GS   */, 0 /* RS   */, 0 /* US   */,
1575     1 /* SPC  */, 1 /* !    */, 1 /* "    */, 1 /* #    */,
1576     1 /* $    */, 1 /* %    */, 1 /* &    */, 1 /* '    */,
1577     1 /* (    */, 1 /* )    */, 1 /* *    */, 1 /* +    */,
1578     1 /* ,    */, 1 /* -    */, 1 /* .    */, 1 /* /    */,
1579     1 /* 0    */, 1 /* 1    */, 1 /* 2    */, 1 /* 3    */,
1580     1 /* 4    */, 1 /* 5    */, 1 /* 6    */, 1 /* 7    */,
1581     1 /* 8    */, 1 /* 9    */, 1 /* :    */, 1 /* ;    */,
1582     1 /* <    */, 1 /* =    */, 1 /* >    */, 1 /* ?    */,
1583     1 /* @    */, 1 /* A    */, 1 /* B    */, 1 /* C    */,
1584     1 /* D    */, 1 /* E    */, 1 /* F    */, 1 /* G    */,
1585     1 /* H    */, 1 /* I    */, 1 /* J    */, 1 /* K    */,
1586     1 /* L    */, 1 /* M    */, 1 /* N    */, 1 /* O    */,
1587     1 /* P    */, 1 /* Q    */, 1 /* R    */, 1 /* S    */,
1588     1 /* T    */, 1 /* U    */, 1 /* V    */, 1 /* W    */,
1589     1 /* X    */, 1 /* Y    */, 1 /* Z    */, 1 /* [    */,
1590     1 /* \    */, 1 /* ]    */, 1 /* ^    */, 1 /* _    */,
1591     1 /* `    */, 1 /* a    */, 1 /* b    */, 1 /* c    */,
1592     1 /* d    */, 1 /* e    */, 1 /* f    */, 1 /* g    */,
1593     1 /* h    */, 1 /* i    */, 1 /* j    */, 1 /* k    */,
1594     1 /* l    */, 1 /* m    */, 1 /* n    */, 1 /* o    */,
1595     1 /* p    */, 1 /* q    */, 1 /* r    */, 1 /* s    */,
1596     1 /* t    */, 1 /* u    */, 1 /* v    */, 1 /* w    */,
1597     1 /* x    */, 1 /* y    */, 1 /* z    */, 1 /* {    */,
1598     1 /* |    */, 1 /* }    */, 1 /* ~    */, 0 /* DEL  */,
1599     1 /* 0x80 */, 1 /* 0x81 */, 1 /* 0x82 */, 1 /* 0x83 */,
1600     1 /* 0x84 */, 1 /* 0x85 */, 1 /* 0x86 */, 1 /* 0x87 */,
1601     1 /* 0x88 */, 1 /* 0x89 */, 1 /* 0x8a */, 1 /* 0x8b */,
1602     1 /* 0x8c */, 1 /* 0x8d */, 1 /* 0x8e */, 1 /* 0x8f */,
1603     1 /* 0x90 */, 1 /* 0x91 */, 1 /* 0x92 */, 1 /* 0x93 */,
1604     1 /* 0x94 */, 1 /* 0x95 */, 1 /* 0x96 */, 1 /* 0x97 */,
1605     1 /* 0x98 */, 1 /* 0x99 */, 1 /* 0x9a */, 1 /* 0x9b */,
1606     1 /* 0x9c */, 1 /* 0x9d */, 1 /* 0x9e */, 1 /* 0x9f */,
1607     1 /* 0xa0 */, 1 /* 0xa1 */, 1 /* 0xa2 */, 1 /* 0xa3 */,
1608     1 /* 0xa4 */, 1 /* 0xa5 */, 1 /* 0xa6 */, 1 /* 0xa7 */,
1609     1 /* 0xa8 */, 1 /* 0xa9 */, 1 /* 0xaa */, 1 /* 0xab */,
1610     1 /* 0xac */, 1 /* 0xad */, 1 /* 0xae */, 1 /* 0xaf */,
1611     1 /* 0xb0 */, 1 /* 0xb1 */, 1 /* 0xb2 */, 1 /* 0xb3 */,
1612     1 /* 0xb4 */, 1 /* 0xb5 */, 1 /* 0xb6 */, 1 /* 0xb7 */,
1613     1 /* 0xb8 */, 1 /* 0xb9 */, 1 /* 0xba */, 1 /* 0xbb */,
1614     1 /* 0xbc */, 1 /* 0xbd */, 1 /* 0xbe */, 1 /* 0xbf */,
1615     1 /* 0xc0 */, 1 /* 0xc1 */, 1 /* 0xc2 */, 1 /* 0xc3 */,
1616     1 /* 0xc4 */, 1 /* 0xc5 */, 1 /* 0xc6 */, 1 /* 0xc7 */,
1617     1 /* 0xc8 */, 1 /* 0xc9 */, 1 /* 0xca */, 1 /* 0xcb */,
1618     1 /* 0xcc */, 1 /* 0xcd */, 1 /* 0xce */, 1 /* 0xcf */,
1619     1 /* 0xd0 */, 1 /* 0xd1 */, 1 /* 0xd2 */, 1 /* 0xd3 */,
1620     1 /* 0xd4 */, 1 /* 0xd5 */, 1 /* 0xd6 */, 1 /* 0xd7 */,
1621     1 /* 0xd8 */, 1 /* 0xd9 */, 1 /* 0xda */, 1 /* 0xdb */,
1622     1 /* 0xdc */, 1 /* 0xdd */, 1 /* 0xde */, 1 /* 0xdf */,
1623     1 /* 0xe0 */, 1 /* 0xe1 */, 1 /* 0xe2 */, 1 /* 0xe3 */,
1624     1 /* 0xe4 */, 1 /* 0xe5 */, 1 /* 0xe6 */, 1 /* 0xe7 */,
1625     1 /* 0xe8 */, 1 /* 0xe9 */, 1 /* 0xea */, 1 /* 0xeb */,
1626     1 /* 0xec */, 1 /* 0xed */, 1 /* 0xee */, 1 /* 0xef */,
1627     1 /* 0xf0 */, 1 /* 0xf1 */, 1 /* 0xf2 */, 1 /* 0xf3 */,
1628     1 /* 0xf4 */, 1 /* 0xf5 */, 1 /* 0xf6 */, 1 /* 0xf7 */,
1629     1 /* 0xf8 */, 1 /* 0xf9 */, 1 /* 0xfa */, 1 /* 0xfb */,
1630     1 /* 0xfc */, 1 /* 0xfd */, 1 /* 0xfe */, 1 /* 0xff */
1631 };
1632 
nghttp3_check_header_value(const uint8_t * value,size_t len)1633 int nghttp3_check_header_value(const uint8_t *value, size_t len) {
1634   const uint8_t *last;
1635 
1636   switch (len) {
1637   case 0:
1638     return 1;
1639   case 1:
1640     return !(*value == ' ' || *value == '\t');
1641   default:
1642     if (*value == ' ' || *value == '\t' || *(value + len - 1) == ' ' ||
1643         *(value + len - 1) == '\t') {
1644       return 0;
1645     }
1646   }
1647 
1648   for (last = value + len; value != last; ++value) {
1649     if (!VALID_HD_VALUE_CHARS[*value]) {
1650       return 0;
1651     }
1652   }
1653   return 1;
1654 }
1655