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