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