1 /*
2 * nghttp2 - HTTP/2 C Library
3 *
4 * Copyright (c) 2013 Tatsuhiro Tsujikawa
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25 #include "nghttp2_hd_test.h"
26
27 #include <stdio.h>
28 #include <assert.h>
29
30 #include "munit.h"
31
32 #include "nghttp2_hd.h"
33 #include "nghttp2_frame.h"
34 #include "nghttp2_test_helper.h"
35 #include "nghttp2_assertion.h"
36
37 static const MunitTest tests[] = {
38 munit_void_test(test_nghttp2_hd_deflate),
39 munit_void_test(test_nghttp2_hd_deflate_same_indexed_repr),
40 munit_void_test(test_nghttp2_hd_inflate_indexed),
41 munit_void_test(test_nghttp2_hd_inflate_indname_noinc),
42 munit_void_test(test_nghttp2_hd_inflate_indname_inc),
43 munit_void_test(test_nghttp2_hd_inflate_indname_inc_eviction),
44 munit_void_test(test_nghttp2_hd_inflate_newname_noinc),
45 munit_void_test(test_nghttp2_hd_inflate_newname_inc),
46 munit_void_test(test_nghttp2_hd_inflate_clearall_inc),
47 munit_void_test(test_nghttp2_hd_inflate_zero_length_huffman),
48 munit_void_test(test_nghttp2_hd_inflate_expect_table_size_update),
49 munit_void_test(test_nghttp2_hd_inflate_unexpected_table_size_update),
50 munit_void_test(test_nghttp2_hd_ringbuf_reserve),
51 munit_void_test(test_nghttp2_hd_change_table_size),
52 munit_void_test(test_nghttp2_hd_deflate_inflate),
53 munit_void_test(test_nghttp2_hd_no_index),
54 munit_void_test(test_nghttp2_hd_deflate_bound),
55 munit_void_test(test_nghttp2_hd_public_api),
56 munit_void_test(test_nghttp2_hd_deflate_hd_vec),
57 munit_void_test(test_nghttp2_hd_decode_length),
58 munit_void_test(test_nghttp2_hd_huff_encode),
59 munit_void_test(test_nghttp2_hd_huff_decode),
60 munit_test_end(),
61 };
62
63 const MunitSuite hd_suite = {
64 "/hd", tests, NULL, 1, MUNIT_SUITE_OPTION_NONE,
65 };
66
test_nghttp2_hd_deflate(void)67 void test_nghttp2_hd_deflate(void) {
68 nghttp2_hd_deflater deflater;
69 nghttp2_hd_inflater inflater;
70 nghttp2_nv nva1[] = {MAKE_NV(":path", "/my-example/index.html"),
71 MAKE_NV(":scheme", "https"), MAKE_NV("hello", "world")};
72 nghttp2_nv nva2[] = {MAKE_NV(":path", "/script.js"),
73 MAKE_NV(":scheme", "https")};
74 nghttp2_nv nva3[] = {MAKE_NV("cookie", "k1=v1"), MAKE_NV("cookie", "k2=v2"),
75 MAKE_NV("via", "proxy")};
76 nghttp2_nv nva4[] = {MAKE_NV(":path", "/style.css"),
77 MAKE_NV("cookie", "k1=v1"), MAKE_NV("cookie", "k1=v1")};
78 nghttp2_nv nva5[] = {MAKE_NV(":path", "/style.css"),
79 MAKE_NV("x-nghttp2", "")};
80 nghttp2_bufs bufs;
81 nghttp2_ssize blocklen;
82 nva_out out;
83 int rv;
84 nghttp2_mem *mem;
85
86 mem = nghttp2_mem_default();
87 frame_pack_bufs_init(&bufs);
88
89 nva_out_init(&out);
90 assert_int(0, ==, nghttp2_hd_deflate_init(&deflater, mem));
91 assert_int(0, ==, nghttp2_hd_inflate_init(&inflater, mem));
92
93 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva1, ARRLEN(nva1));
94 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
95
96 assert_int(0, ==, rv);
97 assert_ptrdiff(0, <, blocklen);
98 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
99
100 assert_size(3, ==, out.nvlen);
101 assert_nv_equal(nva1, out.nva, 3, mem);
102
103 nva_out_reset(&out, mem);
104 nghttp2_bufs_reset(&bufs);
105
106 /* Second headers */
107 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva2, ARRLEN(nva2));
108 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
109
110 assert_int(0, ==, rv);
111 assert_ptrdiff(0, <, blocklen);
112 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
113
114 assert_size(2, ==, out.nvlen);
115 assert_nv_equal(nva2, out.nva, 2, mem);
116
117 nva_out_reset(&out, mem);
118 nghttp2_bufs_reset(&bufs);
119
120 /* Third headers, including same header field name, but value is not
121 the same. */
122 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva3, ARRLEN(nva3));
123 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
124
125 assert_int(0, ==, rv);
126 assert_ptrdiff(0, <, blocklen);
127 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
128
129 assert_size(3, ==, out.nvlen);
130 assert_nv_equal(nva3, out.nva, 3, mem);
131
132 nva_out_reset(&out, mem);
133 nghttp2_bufs_reset(&bufs);
134
135 /* Fourth headers, including duplicate header fields. */
136 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva4, ARRLEN(nva4));
137 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
138
139 assert_int(0, ==, rv);
140 assert_ptrdiff(0, <, blocklen);
141 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
142
143 assert_size(3, ==, out.nvlen);
144 assert_nv_equal(nva4, out.nva, 3, mem);
145
146 nva_out_reset(&out, mem);
147 nghttp2_bufs_reset(&bufs);
148
149 /* Fifth headers includes empty value */
150 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva5, ARRLEN(nva5));
151 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
152
153 assert_int(0, ==, rv);
154 assert_ptrdiff(0, <, blocklen);
155 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
156
157 assert_size(2, ==, out.nvlen);
158 assert_nv_equal(nva5, out.nva, 2, mem);
159
160 nva_out_reset(&out, mem);
161 nghttp2_bufs_reset(&bufs);
162
163 /* Cleanup */
164 nghttp2_bufs_free(&bufs);
165 nghttp2_hd_inflate_free(&inflater);
166 nghttp2_hd_deflate_free(&deflater);
167 }
168
test_nghttp2_hd_deflate_same_indexed_repr(void)169 void test_nghttp2_hd_deflate_same_indexed_repr(void) {
170 nghttp2_hd_deflater deflater;
171 nghttp2_hd_inflater inflater;
172 nghttp2_nv nva1[] = {MAKE_NV("host", "alpha"), MAKE_NV("host", "alpha")};
173 nghttp2_nv nva2[] = {MAKE_NV("host", "alpha"), MAKE_NV("host", "alpha"),
174 MAKE_NV("host", "alpha")};
175 nghttp2_bufs bufs;
176 nghttp2_ssize blocklen;
177 nva_out out;
178 int rv;
179 nghttp2_mem *mem;
180
181 mem = nghttp2_mem_default();
182 frame_pack_bufs_init(&bufs);
183
184 nva_out_init(&out);
185 assert_int(0, ==, nghttp2_hd_deflate_init(&deflater, mem));
186 assert_int(0, ==, nghttp2_hd_inflate_init(&inflater, mem));
187
188 /* Encode 2 same headers. Emit 1 literal reprs and 1 index repr. */
189 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva1, ARRLEN(nva1));
190 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
191
192 assert_int(0, ==, rv);
193 assert_ptrdiff(0, <, blocklen);
194 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
195
196 assert_size(2, ==, out.nvlen);
197 assert_nv_equal(nva1, out.nva, 2, mem);
198
199 nva_out_reset(&out, mem);
200 nghttp2_bufs_reset(&bufs);
201
202 /* Encode 3 same headers. This time, emits 3 index reprs. */
203 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva2, ARRLEN(nva2));
204 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
205
206 assert_int(0, ==, rv);
207 assert_ptrdiff(3, ==, blocklen);
208 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
209
210 assert_size(3, ==, out.nvlen);
211 assert_nv_equal(nva2, out.nva, 3, mem);
212
213 nva_out_reset(&out, mem);
214 nghttp2_bufs_reset(&bufs);
215
216 /* Cleanup */
217 nghttp2_bufs_free(&bufs);
218 nghttp2_hd_inflate_free(&inflater);
219 nghttp2_hd_deflate_free(&deflater);
220 }
221
test_nghttp2_hd_inflate_indexed(void)222 void test_nghttp2_hd_inflate_indexed(void) {
223 nghttp2_hd_inflater inflater;
224 nghttp2_bufs bufs;
225 nghttp2_ssize blocklen;
226 nghttp2_nv nv = MAKE_NV(":path", "/");
227 nva_out out;
228 nghttp2_mem *mem;
229
230 mem = nghttp2_mem_default();
231 frame_pack_bufs_init(&bufs);
232
233 nva_out_init(&out);
234 nghttp2_hd_inflate_init(&inflater, mem);
235
236 nghttp2_bufs_addb(&bufs, (1 << 7) | 4);
237
238 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
239
240 assert_ptrdiff(1, ==, blocklen);
241 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
242
243 assert_size(1, ==, out.nvlen);
244
245 assert_nv_equal(&nv, out.nva, 1, mem);
246
247 nva_out_reset(&out, mem);
248 nghttp2_bufs_reset(&bufs);
249
250 /* index = 0 is error */
251 nghttp2_bufs_addb(&bufs, 1 << 7);
252
253 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
254
255 assert_ptrdiff(1, ==, blocklen);
256 assert_ptrdiff(NGHTTP2_ERR_HEADER_COMP, ==,
257 inflate_hd(&inflater, &out, &bufs, 0, mem));
258
259 nghttp2_bufs_free(&bufs);
260 nghttp2_hd_inflate_free(&inflater);
261 }
262
test_nghttp2_hd_inflate_indname_noinc(void)263 void test_nghttp2_hd_inflate_indname_noinc(void) {
264 nghttp2_hd_inflater inflater;
265 nghttp2_bufs bufs;
266 nghttp2_ssize blocklen;
267 nghttp2_nv nv[] = {/* Huffman */
268 MAKE_NV("user-agent", "nghttp2"),
269 /* Expecting no huffman */
270 MAKE_NV("user-agent", "x")};
271 size_t i;
272 nva_out out;
273 nghttp2_mem *mem;
274
275 mem = nghttp2_mem_default();
276 frame_pack_bufs_init(&bufs);
277
278 nva_out_init(&out);
279 nghttp2_hd_inflate_init(&inflater, mem);
280
281 for (i = 0; i < ARRLEN(nv); ++i) {
282 assert_int(0, ==,
283 nghttp2_hd_emit_indname_block(&bufs, 57, &nv[i],
284 NGHTTP2_HD_WITHOUT_INDEXING));
285
286 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
287
288 assert_ptrdiff(0, <, blocklen);
289 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
290
291 assert_size(1, ==, out.nvlen);
292 assert_nv_equal(&nv[i], out.nva, 1, mem);
293 assert_size(0, ==, inflater.ctx.hd_table.len);
294 assert_size(61, ==, nghttp2_hd_inflate_get_num_table_entries(&inflater));
295
296 nva_out_reset(&out, mem);
297 nghttp2_bufs_reset(&bufs);
298 }
299
300 nghttp2_bufs_free(&bufs);
301 nghttp2_hd_inflate_free(&inflater);
302 }
303
test_nghttp2_hd_inflate_indname_inc(void)304 void test_nghttp2_hd_inflate_indname_inc(void) {
305 nghttp2_hd_inflater inflater;
306 nghttp2_bufs bufs;
307 nghttp2_ssize blocklen;
308 nghttp2_nv nv = MAKE_NV("user-agent", "nghttp2");
309 nva_out out;
310 nghttp2_mem *mem;
311
312 mem = nghttp2_mem_default();
313 frame_pack_bufs_init(&bufs);
314
315 nva_out_init(&out);
316 nghttp2_hd_inflate_init(&inflater, mem);
317
318 assert_int(
319 0, ==,
320 nghttp2_hd_emit_indname_block(&bufs, 57, &nv, NGHTTP2_HD_WITH_INDEXING));
321
322 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
323
324 assert_ptrdiff(0, <, blocklen);
325 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
326
327 assert_size(1, ==, out.nvlen);
328 assert_nv_equal(&nv, out.nva, 1, mem);
329 assert_size(1, ==, inflater.ctx.hd_table.len);
330 assert_size(62, ==, nghttp2_hd_inflate_get_num_table_entries(&inflater));
331 assert_nv_equal(
332 &nv,
333 nghttp2_hd_inflate_get_table_entry(
334 &inflater, NGHTTP2_STATIC_TABLE_LENGTH + inflater.ctx.hd_table.len),
335 1, mem);
336
337 nva_out_reset(&out, mem);
338 nghttp2_bufs_free(&bufs);
339 nghttp2_hd_inflate_free(&inflater);
340 }
341
test_nghttp2_hd_inflate_indname_inc_eviction(void)342 void test_nghttp2_hd_inflate_indname_inc_eviction(void) {
343 nghttp2_hd_inflater inflater;
344 nghttp2_bufs bufs;
345 nghttp2_ssize blocklen;
346 uint8_t value[1025];
347 nva_out out;
348 nghttp2_nv nv;
349 nghttp2_mem *mem;
350
351 mem = nghttp2_mem_default();
352 frame_pack_bufs_init(&bufs);
353
354 nva_out_init(&out);
355 nghttp2_hd_inflate_init(&inflater, mem);
356
357 memset(value, '0', sizeof(value));
358 value[sizeof(value) - 1] = '\0';
359 nv.value = value;
360 nv.valuelen = sizeof(value) - 1;
361
362 nv.flags = NGHTTP2_NV_FLAG_NONE;
363
364 assert_int(
365 0, ==,
366 nghttp2_hd_emit_indname_block(&bufs, 14, &nv, NGHTTP2_HD_WITH_INDEXING));
367 assert_int(
368 0, ==,
369 nghttp2_hd_emit_indname_block(&bufs, 15, &nv, NGHTTP2_HD_WITH_INDEXING));
370 assert_int(
371 0, ==,
372 nghttp2_hd_emit_indname_block(&bufs, 16, &nv, NGHTTP2_HD_WITH_INDEXING));
373 assert_int(
374 0, ==,
375 nghttp2_hd_emit_indname_block(&bufs, 17, &nv, NGHTTP2_HD_WITH_INDEXING));
376
377 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
378
379 assert_ptrdiff(0, <, blocklen);
380
381 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
382
383 assert_size(4, ==, out.nvlen);
384 assert_size(14, ==, out.nva[0].namelen);
385 assert_memory_equal(out.nva[0].namelen, "accept-charset", out.nva[0].name);
386 assert_size(sizeof(value) - 1, ==, out.nva[0].valuelen);
387
388 nva_out_reset(&out, mem);
389 nghttp2_bufs_reset(&bufs);
390
391 assert_size(3, ==, inflater.ctx.hd_table.len);
392 assert_size(64, ==, nghttp2_hd_inflate_get_num_table_entries(&inflater));
393
394 nghttp2_bufs_free(&bufs);
395 nghttp2_hd_inflate_free(&inflater);
396 }
397
test_nghttp2_hd_inflate_newname_noinc(void)398 void test_nghttp2_hd_inflate_newname_noinc(void) {
399 nghttp2_hd_inflater inflater;
400 nghttp2_bufs bufs;
401 nghttp2_ssize blocklen;
402 nghttp2_nv nv[] = {/* Expecting huffman for both */
403 MAKE_NV("my-long-content-length", "nghttp2"),
404 /* Expecting no huffman for both */
405 MAKE_NV("x", "y"),
406 /* Huffman for key only */
407 MAKE_NV("my-long-content-length", "y"),
408 /* Huffman for value only */
409 MAKE_NV("x", "nghttp2")};
410 size_t i;
411 nva_out out;
412 nghttp2_mem *mem;
413
414 mem = nghttp2_mem_default();
415 frame_pack_bufs_init(&bufs);
416
417 nva_out_init(&out);
418 nghttp2_hd_inflate_init(&inflater, mem);
419 for (i = 0; i < ARRLEN(nv); ++i) {
420 assert_int(0, ==,
421 nghttp2_hd_emit_newname_block(&bufs, &nv[i],
422 NGHTTP2_HD_WITHOUT_INDEXING));
423
424 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
425
426 assert_ptrdiff(0, <, blocklen);
427 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
428
429 assert_size(1, ==, out.nvlen);
430 assert_nv_equal(&nv[i], out.nva, 1, mem);
431 assert_size(0, ==, inflater.ctx.hd_table.len);
432
433 nva_out_reset(&out, mem);
434 nghttp2_bufs_reset(&bufs);
435 }
436
437 nghttp2_bufs_free(&bufs);
438 nghttp2_hd_inflate_free(&inflater);
439 }
440
test_nghttp2_hd_inflate_newname_inc(void)441 void test_nghttp2_hd_inflate_newname_inc(void) {
442 nghttp2_hd_inflater inflater;
443 nghttp2_bufs bufs;
444 nghttp2_ssize blocklen;
445 nghttp2_nv nv = MAKE_NV("x-rel", "nghttp2");
446 nva_out out;
447 nghttp2_mem *mem;
448
449 mem = nghttp2_mem_default();
450 frame_pack_bufs_init(&bufs);
451
452 nva_out_init(&out);
453 nghttp2_hd_inflate_init(&inflater, mem);
454
455 assert_int(
456 0, ==,
457 nghttp2_hd_emit_newname_block(&bufs, &nv, NGHTTP2_HD_WITH_INDEXING));
458
459 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
460
461 assert_ptrdiff(0, <, blocklen);
462 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
463
464 assert_size(1, ==, out.nvlen);
465 assert_nv_equal(&nv, out.nva, 1, mem);
466 assert_size(1, ==, inflater.ctx.hd_table.len);
467 assert_nv_equal(
468 &nv,
469 nghttp2_hd_inflate_get_table_entry(
470 &inflater, NGHTTP2_STATIC_TABLE_LENGTH + inflater.ctx.hd_table.len),
471 1, mem);
472
473 nva_out_reset(&out, mem);
474 nghttp2_bufs_free(&bufs);
475 nghttp2_hd_inflate_free(&inflater);
476 }
477
test_nghttp2_hd_inflate_clearall_inc(void)478 void test_nghttp2_hd_inflate_clearall_inc(void) {
479 nghttp2_hd_inflater inflater;
480 nghttp2_bufs bufs;
481 nghttp2_ssize blocklen;
482 nghttp2_nv nv;
483 uint8_t value[4061];
484 nva_out out;
485 nghttp2_mem *mem;
486
487 mem = nghttp2_mem_default();
488 bufs_large_init(&bufs, 8192);
489
490 nva_out_init(&out);
491 /* Total 4097 bytes space required to hold this entry */
492 nv.name = (uint8_t *)"alpha";
493 nv.namelen = strlen((char *)nv.name);
494 memset(value, '0', sizeof(value));
495 value[sizeof(value) - 1] = '\0';
496 nv.value = value;
497 nv.valuelen = sizeof(value) - 1;
498
499 nv.flags = NGHTTP2_NV_FLAG_NONE;
500
501 nghttp2_hd_inflate_init(&inflater, mem);
502
503 assert_int(
504 0, ==,
505 nghttp2_hd_emit_newname_block(&bufs, &nv, NGHTTP2_HD_WITH_INDEXING));
506
507 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
508
509 assert_ptrdiff(0, <, blocklen);
510 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
511
512 assert_size(1, ==, out.nvlen);
513 assert_nv_equal(&nv, out.nva, 1, mem);
514 assert_size(0, ==, inflater.ctx.hd_table.len);
515
516 nva_out_reset(&out, mem);
517
518 /* Do it again */
519 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
520
521 assert_size(1, ==, out.nvlen);
522 assert_nv_equal(&nv, out.nva, 1, mem);
523 assert_size(0, ==, inflater.ctx.hd_table.len);
524
525 nva_out_reset(&out, mem);
526 nghttp2_bufs_reset(&bufs);
527
528 /* This time, 4096 bytes space required, which is just fits in the
529 header table */
530 nv.valuelen = sizeof(value) - 2;
531
532 assert_int(
533 0, ==,
534 nghttp2_hd_emit_newname_block(&bufs, &nv, NGHTTP2_HD_WITH_INDEXING));
535
536 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
537
538 assert_ptrdiff(0, <, blocklen);
539 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
540
541 assert_size(1, ==, out.nvlen);
542 assert_nv_equal(&nv, out.nva, 1, mem);
543 assert_size(1, ==, inflater.ctx.hd_table.len);
544
545 nva_out_reset(&out, mem);
546 nghttp2_bufs_reset(&bufs);
547
548 nghttp2_bufs_free(&bufs);
549 nghttp2_hd_inflate_free(&inflater);
550 }
551
test_nghttp2_hd_inflate_zero_length_huffman(void)552 void test_nghttp2_hd_inflate_zero_length_huffman(void) {
553 nghttp2_hd_inflater inflater;
554 nghttp2_bufs bufs;
555 /* Literal header without indexing - new name */
556 uint8_t data[] = {0x40, 0x01, 0x78 /* 'x' */, 0x80};
557 nva_out out;
558 nghttp2_mem *mem;
559
560 mem = nghttp2_mem_default();
561 frame_pack_bufs_init(&bufs);
562
563 nva_out_init(&out);
564
565 nghttp2_bufs_add(&bufs, data, sizeof(data));
566
567 /* /\* Literal header without indexing - new name *\/ */
568 /* ptr[0] = 0x40; */
569 /* ptr[1] = 1; */
570 /* ptr[2] = 'x'; */
571 /* ptr[3] = 0x80; */
572
573 nghttp2_hd_inflate_init(&inflater, mem);
574 assert_ptrdiff(4, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
575
576 assert_size(1, ==, out.nvlen);
577 assert_size(1, ==, out.nva[0].namelen);
578 assert_uint8('x', ==, out.nva[0].name[0]);
579 assert_null(out.nva[0].value);
580 assert_size(0, ==, out.nva[0].valuelen);
581
582 nva_out_reset(&out, mem);
583 nghttp2_bufs_free(&bufs);
584 nghttp2_hd_inflate_free(&inflater);
585 }
586
test_nghttp2_hd_inflate_expect_table_size_update(void)587 void test_nghttp2_hd_inflate_expect_table_size_update(void) {
588 nghttp2_hd_inflater inflater;
589 nghttp2_bufs bufs;
590 nghttp2_mem *mem;
591 /* Indexed Header: :method: GET */
592 uint8_t data[] = {0x82};
593 nva_out out;
594
595 mem = nghttp2_mem_default();
596 frame_pack_bufs_init(&bufs);
597 nva_out_init(&out);
598
599 nghttp2_bufs_add(&bufs, data, sizeof(data));
600 nghttp2_hd_inflate_init(&inflater, mem);
601 /* This will make inflater require table size update in the next
602 inflation. */
603 nghttp2_hd_inflate_change_table_size(&inflater, 4095);
604 nghttp2_hd_inflate_change_table_size(&inflater, 4096);
605 assert_ptrdiff(NGHTTP2_ERR_HEADER_COMP, ==,
606 inflate_hd(&inflater, &out, &bufs, 0, mem));
607
608 nva_out_reset(&out, mem);
609 nghttp2_hd_inflate_free(&inflater);
610
611 /* This does not require for encoder to emit table size update since
612 * size is not changed. */
613 nghttp2_hd_inflate_init(&inflater, mem);
614 nghttp2_hd_inflate_change_table_size(&inflater, 4096);
615 assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==,
616 inflate_hd(&inflater, &out, &bufs, 0, mem));
617
618 nva_out_reset(&out, mem);
619 nghttp2_hd_inflate_free(&inflater);
620
621 /* This does not require for encodre to emit table size update since
622 new size is larger than current size. */
623 nghttp2_hd_inflate_init(&inflater, mem);
624 nghttp2_hd_inflate_change_table_size(&inflater, 4097);
625 assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==,
626 inflate_hd(&inflater, &out, &bufs, 0, mem));
627
628 nva_out_reset(&out, mem);
629 nghttp2_hd_inflate_free(&inflater);
630
631 /* Received table size is strictly larger than minimum table size */
632 nghttp2_hd_inflate_init(&inflater, mem);
633 nghttp2_hd_inflate_change_table_size(&inflater, 111);
634 nghttp2_hd_inflate_change_table_size(&inflater, 4096);
635
636 nghttp2_bufs_reset(&bufs);
637 nghttp2_hd_emit_table_size(&bufs, 112);
638
639 assert_ptrdiff(NGHTTP2_ERR_HEADER_COMP, ==,
640 inflate_hd(&inflater, &out, &bufs, 0, mem));
641
642 nva_out_reset(&out, mem);
643 nghttp2_hd_inflate_free(&inflater);
644
645 /* Receiving 2 table size updates, min and last value */
646 nghttp2_hd_inflate_init(&inflater, mem);
647 nghttp2_hd_inflate_change_table_size(&inflater, 111);
648 nghttp2_hd_inflate_change_table_size(&inflater, 4096);
649
650 nghttp2_bufs_reset(&bufs);
651 nghttp2_hd_emit_table_size(&bufs, 111);
652 nghttp2_hd_emit_table_size(&bufs, 4096);
653
654 assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==,
655 inflate_hd(&inflater, &out, &bufs, 0, mem));
656
657 nva_out_reset(&out, mem);
658 nghttp2_hd_inflate_free(&inflater);
659
660 /* 2nd update is larger than last value */
661 nghttp2_hd_inflate_init(&inflater, mem);
662 nghttp2_hd_inflate_change_table_size(&inflater, 111);
663 nghttp2_hd_inflate_change_table_size(&inflater, 4095);
664
665 nghttp2_bufs_reset(&bufs);
666 nghttp2_hd_emit_table_size(&bufs, 111);
667 nghttp2_hd_emit_table_size(&bufs, 4096);
668
669 assert_ptrdiff(NGHTTP2_ERR_HEADER_COMP, ==,
670 inflate_hd(&inflater, &out, &bufs, 0, mem));
671
672 nva_out_reset(&out, mem);
673 nghttp2_hd_inflate_free(&inflater);
674
675 nghttp2_bufs_free(&bufs);
676 }
677
test_nghttp2_hd_inflate_unexpected_table_size_update(void)678 void test_nghttp2_hd_inflate_unexpected_table_size_update(void) {
679 nghttp2_hd_inflater inflater;
680 nghttp2_bufs bufs;
681 nghttp2_mem *mem;
682 /* Indexed Header: :method: GET, followed by table size update.
683 This violates RFC 7541. */
684 uint8_t data[] = {0x82, 0x20};
685 nva_out out;
686
687 mem = nghttp2_mem_default();
688 frame_pack_bufs_init(&bufs);
689 nva_out_init(&out);
690
691 nghttp2_bufs_add(&bufs, data, sizeof(data));
692 nghttp2_hd_inflate_init(&inflater, mem);
693 assert_ptrdiff(NGHTTP2_ERR_HEADER_COMP, ==,
694 inflate_hd(&inflater, &out, &bufs, 0, mem));
695
696 nva_out_reset(&out, mem);
697 nghttp2_bufs_free(&bufs);
698 nghttp2_hd_inflate_free(&inflater);
699 }
700
test_nghttp2_hd_ringbuf_reserve(void)701 void test_nghttp2_hd_ringbuf_reserve(void) {
702 nghttp2_hd_deflater deflater;
703 nghttp2_hd_inflater inflater;
704 nghttp2_nv nv;
705 nghttp2_bufs bufs;
706 nva_out out;
707 int i;
708 nghttp2_ssize rv;
709 nghttp2_ssize blocklen;
710 nghttp2_mem *mem;
711
712 mem = nghttp2_mem_default();
713 frame_pack_bufs_init(&bufs);
714 nva_out_init(&out);
715
716 nv.flags = NGHTTP2_NV_FLAG_NONE;
717 nv.name = (uint8_t *)"a";
718 nv.namelen = strlen((const char *)nv.name);
719 nv.valuelen = 4;
720 nv.value = mem->malloc(nv.valuelen + 1, NULL);
721 memset(nv.value, 0, nv.valuelen);
722
723 nghttp2_hd_deflate_init2(&deflater, 8000, mem);
724 nghttp2_hd_inflate_init(&inflater, mem);
725
726 nghttp2_hd_inflate_change_table_size(&inflater, 8000);
727 nghttp2_hd_deflate_change_table_size(&deflater, 8000);
728
729 for (i = 0; i < 150; ++i) {
730 memcpy(nv.value, &i, sizeof(i));
731 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, &nv, 1);
732 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
733
734 assert_ptrdiff(0, ==, rv);
735 assert_ptrdiff(0, <, blocklen);
736
737 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
738
739 assert_size(1, ==, out.nvlen);
740 assert_nv_equal(&nv, out.nva, 1, mem);
741
742 nva_out_reset(&out, mem);
743 nghttp2_bufs_reset(&bufs);
744 }
745
746 nghttp2_bufs_free(&bufs);
747 nghttp2_hd_inflate_free(&inflater);
748 nghttp2_hd_deflate_free(&deflater);
749
750 mem->free(nv.value, NULL);
751 }
752
test_nghttp2_hd_change_table_size(void)753 void test_nghttp2_hd_change_table_size(void) {
754 nghttp2_hd_deflater deflater;
755 nghttp2_hd_inflater inflater;
756 nghttp2_nv nva[] = {MAKE_NV("alpha", "bravo"), MAKE_NV("charlie", "delta")};
757 nghttp2_nv nva2[] = {MAKE_NV(":path", "/")};
758 nghttp2_bufs bufs;
759 int rv;
760 nva_out out;
761 nghttp2_ssize blocklen;
762 nghttp2_mem *mem;
763
764 mem = nghttp2_mem_default();
765 frame_pack_bufs_init(&bufs);
766
767 nva_out_init(&out);
768
769 nghttp2_hd_deflate_init(&deflater, mem);
770 nghttp2_hd_inflate_init(&inflater, mem);
771
772 /* inflater changes notifies 8000 max header table size */
773 assert_int(0, ==, nghttp2_hd_inflate_change_table_size(&inflater, 8000));
774 assert_int(0, ==, nghttp2_hd_deflate_change_table_size(&deflater, 8000));
775
776 assert_size(4096, ==, deflater.ctx.hd_table_bufsize_max);
777
778 assert_size(4096, ==, inflater.ctx.hd_table_bufsize_max);
779 assert_size(8000, ==, inflater.settings_hd_table_bufsize_max);
780
781 /* This will emit encoding context update with header table size 4096 */
782 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
783 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
784
785 assert_int(0, ==, rv);
786 assert_ptrdiff(0, <, blocklen);
787 assert_size(2, ==, deflater.ctx.hd_table.len);
788 assert_size(63, ==, nghttp2_hd_deflate_get_num_table_entries(&deflater));
789 assert_size(4096, ==, deflater.ctx.hd_table_bufsize_max);
790
791 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
792 assert_size(2, ==, inflater.ctx.hd_table.len);
793 assert_size(63, ==, nghttp2_hd_inflate_get_num_table_entries(&inflater));
794 assert_size(4096, ==, inflater.ctx.hd_table_bufsize_max);
795 assert_size(8000, ==, inflater.settings_hd_table_bufsize_max);
796
797 nva_out_reset(&out, mem);
798 nghttp2_bufs_reset(&bufs);
799
800 /* inflater changes header table size to 1024 */
801 assert_int(0, ==, nghttp2_hd_inflate_change_table_size(&inflater, 1024));
802 assert_int(0, ==, nghttp2_hd_deflate_change_table_size(&deflater, 1024));
803
804 assert_size(1024, ==, deflater.ctx.hd_table_bufsize_max);
805
806 assert_size(1024, ==, inflater.ctx.hd_table_bufsize_max);
807 assert_size(1024, ==, inflater.settings_hd_table_bufsize_max);
808
809 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
810 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
811
812 assert_int(0, ==, rv);
813 assert_ptrdiff(0, <, blocklen);
814 assert_size(2, ==, deflater.ctx.hd_table.len);
815 assert_size(63, ==, nghttp2_hd_deflate_get_num_table_entries(&deflater));
816 assert_size(1024, ==, deflater.ctx.hd_table_bufsize_max);
817
818 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
819 assert_size(2, ==, inflater.ctx.hd_table.len);
820 assert_size(63, ==, nghttp2_hd_inflate_get_num_table_entries(&inflater));
821 assert_size(1024, ==, inflater.ctx.hd_table_bufsize_max);
822 assert_size(1024, ==, inflater.settings_hd_table_bufsize_max);
823
824 nva_out_reset(&out, mem);
825 nghttp2_bufs_reset(&bufs);
826
827 /* inflater changes header table size to 0 */
828 assert_int(0, ==, nghttp2_hd_inflate_change_table_size(&inflater, 0));
829 assert_int(0, ==, nghttp2_hd_deflate_change_table_size(&deflater, 0));
830
831 assert_size(0, ==, deflater.ctx.hd_table.len);
832 assert_size(61, ==, nghttp2_hd_deflate_get_num_table_entries(&deflater));
833 assert_size(0, ==, deflater.ctx.hd_table_bufsize_max);
834
835 assert_size(0, ==, inflater.ctx.hd_table.len);
836 assert_size(61, ==, nghttp2_hd_inflate_get_num_table_entries(&inflater));
837 assert_size(0, ==, inflater.ctx.hd_table_bufsize_max);
838 assert_size(0, ==, inflater.settings_hd_table_bufsize_max);
839
840 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
841 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
842
843 assert_int(0, ==, rv);
844 assert_ptrdiff(0, <, blocklen);
845 assert_size(0, ==, deflater.ctx.hd_table.len);
846 assert_size(61, ==, nghttp2_hd_deflate_get_num_table_entries(&deflater));
847 assert_size(0, ==, deflater.ctx.hd_table_bufsize_max);
848
849 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
850 assert_size(0, ==, inflater.ctx.hd_table.len);
851 assert_size(61, ==, nghttp2_hd_inflate_get_num_table_entries(&inflater));
852 assert_size(0, ==, inflater.ctx.hd_table_bufsize_max);
853 assert_size(0, ==, inflater.settings_hd_table_bufsize_max);
854
855 nva_out_reset(&out, mem);
856 nghttp2_bufs_reset(&bufs);
857
858 nghttp2_bufs_free(&bufs);
859 nghttp2_hd_inflate_free(&inflater);
860 nghttp2_hd_deflate_free(&deflater);
861
862 /* Check table buffer is expanded */
863 frame_pack_bufs_init(&bufs);
864
865 nghttp2_hd_deflate_init2(&deflater, 8192, mem);
866 nghttp2_hd_inflate_init(&inflater, mem);
867
868 /* First inflater changes header table size to 8000 */
869 assert_int(0, ==, nghttp2_hd_inflate_change_table_size(&inflater, 8000));
870 assert_int(0, ==, nghttp2_hd_deflate_change_table_size(&deflater, 8000));
871
872 assert_size(8000, ==, deflater.ctx.hd_table_bufsize_max);
873 assert_size(8000, ==,
874 nghttp2_hd_deflate_get_max_dynamic_table_size(&deflater));
875 assert_size(4096, ==, inflater.ctx.hd_table_bufsize_max);
876 assert_size(4096, ==,
877 nghttp2_hd_inflate_get_max_dynamic_table_size(&inflater));
878 assert_size(8000, ==, inflater.settings_hd_table_bufsize_max);
879
880 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
881 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
882
883 assert_int(0, ==, rv);
884 assert_ptrdiff(0, <, blocklen);
885 assert_size(2, ==, deflater.ctx.hd_table.len);
886 assert_size(8000, ==, deflater.ctx.hd_table_bufsize_max);
887
888 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
889 assert_size(2, ==, inflater.ctx.hd_table.len);
890 assert_size(8000, ==, inflater.ctx.hd_table_bufsize_max);
891 assert_size(8000, ==, inflater.settings_hd_table_bufsize_max);
892
893 nva_out_reset(&out, mem);
894 nghttp2_bufs_reset(&bufs);
895
896 assert_int(0, ==, nghttp2_hd_inflate_change_table_size(&inflater, 16383));
897 assert_int(0, ==, nghttp2_hd_deflate_change_table_size(&deflater, 16383));
898
899 assert_size(8192, ==, deflater.ctx.hd_table_bufsize_max);
900 assert_size(8192, ==,
901 nghttp2_hd_deflate_get_max_dynamic_table_size(&deflater));
902
903 assert_size(8000, ==, inflater.ctx.hd_table_bufsize_max);
904 assert_size(8000, ==,
905 nghttp2_hd_inflate_get_max_dynamic_table_size(&inflater));
906 assert_size(16383, ==, inflater.settings_hd_table_bufsize_max);
907
908 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
909 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
910
911 assert_int(0, ==, rv);
912 assert_ptrdiff(0, <, blocklen);
913 assert_size(2, ==, deflater.ctx.hd_table.len);
914 assert_size(8192, ==, deflater.ctx.hd_table_bufsize_max);
915
916 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
917 assert_size(2, ==, inflater.ctx.hd_table.len);
918 assert_size(8192, ==, inflater.ctx.hd_table_bufsize_max);
919 assert_size(16383, ==, inflater.settings_hd_table_bufsize_max);
920
921 nva_out_reset(&out, mem);
922 nghttp2_bufs_reset(&bufs);
923
924 /* Lastly, check the error condition */
925
926 rv = nghttp2_hd_emit_table_size(&bufs, 25600);
927 assert_int(0, ==, rv);
928 assert_ptrdiff(NGHTTP2_ERR_HEADER_COMP, ==,
929 inflate_hd(&inflater, &out, &bufs, 0, mem));
930
931 nva_out_reset(&out, mem);
932 nghttp2_bufs_reset(&bufs);
933
934 nghttp2_hd_inflate_free(&inflater);
935 nghttp2_hd_deflate_free(&deflater);
936
937 /* Check that encoder can handle the case where its allowable buffer
938 size is less than default size, 4096 */
939 nghttp2_hd_deflate_init2(&deflater, 1024, mem);
940 nghttp2_hd_inflate_init(&inflater, mem);
941
942 assert_size(1024, ==, deflater.ctx.hd_table_bufsize_max);
943
944 /* This emits context update with buffer size 1024 */
945 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
946 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
947
948 assert_int(0, ==, rv);
949 assert_ptrdiff(0, <, blocklen);
950 assert_size(2, ==, deflater.ctx.hd_table.len);
951 assert_size(1024, ==, deflater.ctx.hd_table_bufsize_max);
952
953 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
954 assert_size(2, ==, inflater.ctx.hd_table.len);
955 assert_size(1024, ==, inflater.ctx.hd_table_bufsize_max);
956 assert_size(4096, ==, inflater.settings_hd_table_bufsize_max);
957
958 nva_out_reset(&out, mem);
959 nghttp2_bufs_reset(&bufs);
960
961 nghttp2_hd_inflate_free(&inflater);
962 nghttp2_hd_deflate_free(&deflater);
963
964 /* Check that table size UINT32_MAX can be received */
965 nghttp2_hd_deflate_init2(&deflater, UINT32_MAX, mem);
966 nghttp2_hd_inflate_init(&inflater, mem);
967
968 assert_int(0, ==,
969 nghttp2_hd_inflate_change_table_size(&inflater, UINT32_MAX));
970 assert_int(0, ==,
971 nghttp2_hd_deflate_change_table_size(&deflater, UINT32_MAX));
972
973 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
974 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
975
976 assert_int(0, ==, rv);
977 assert_size(UINT32_MAX, ==, deflater.ctx.hd_table_bufsize_max);
978
979 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
980 assert_size(UINT32_MAX, ==, inflater.ctx.hd_table_bufsize_max);
981 assert_size(UINT32_MAX, ==, inflater.settings_hd_table_bufsize_max);
982
983 nva_out_reset(&out, mem);
984 nghttp2_bufs_reset(&bufs);
985
986 nghttp2_hd_inflate_free(&inflater);
987 nghttp2_hd_deflate_free(&deflater);
988
989 /* Check that context update emitted twice */
990 nghttp2_hd_deflate_init2(&deflater, 4096, mem);
991 nghttp2_hd_inflate_init(&inflater, mem);
992
993 assert_int(0, ==, nghttp2_hd_inflate_change_table_size(&inflater, 0));
994 assert_int(0, ==, nghttp2_hd_inflate_change_table_size(&inflater, 3000));
995 assert_int(0, ==, nghttp2_hd_deflate_change_table_size(&deflater, 0));
996 assert_int(0, ==, nghttp2_hd_deflate_change_table_size(&deflater, 3000));
997
998 assert_size(0, ==, deflater.min_hd_table_bufsize_max);
999 assert_size(3000, ==, deflater.ctx.hd_table_bufsize_max);
1000
1001 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva2, 1);
1002 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
1003
1004 assert_int(0, ==, rv);
1005 assert_ptrdiff(3, <, blocklen);
1006 assert_size(3000, ==, deflater.ctx.hd_table_bufsize_max);
1007 assert_size(UINT32_MAX, ==, deflater.min_hd_table_bufsize_max);
1008
1009 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
1010 assert_size(3000, ==, inflater.ctx.hd_table_bufsize_max);
1011 assert_size(3000, ==, inflater.settings_hd_table_bufsize_max);
1012
1013 nva_out_reset(&out, mem);
1014 nghttp2_bufs_reset(&bufs);
1015
1016 nghttp2_hd_inflate_free(&inflater);
1017 nghttp2_hd_deflate_free(&deflater);
1018
1019 nghttp2_bufs_free(&bufs);
1020 }
1021
check_deflate_inflate(nghttp2_hd_deflater * deflater,nghttp2_hd_inflater * inflater,nghttp2_nv * nva,size_t nvlen,nghttp2_mem * mem)1022 static void check_deflate_inflate(nghttp2_hd_deflater *deflater,
1023 nghttp2_hd_inflater *inflater,
1024 nghttp2_nv *nva, size_t nvlen,
1025 nghttp2_mem *mem) {
1026 nghttp2_bufs bufs;
1027 nghttp2_ssize blocklen;
1028 nva_out out;
1029 int rv;
1030
1031 frame_pack_bufs_init(&bufs);
1032
1033 nva_out_init(&out);
1034 rv = nghttp2_hd_deflate_hd_bufs(deflater, &bufs, nva, nvlen);
1035 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
1036
1037 assert_int(0, ==, rv);
1038 assert_ptrdiff(0, <=, blocklen);
1039
1040 assert_ptrdiff(blocklen, ==, inflate_hd(inflater, &out, &bufs, 0, mem));
1041
1042 assert_size(nvlen, ==, out.nvlen);
1043 assert_nv_equal(nva, out.nva, nvlen, mem);
1044
1045 nva_out_reset(&out, mem);
1046 nghttp2_bufs_free(&bufs);
1047 }
1048
test_nghttp2_hd_deflate_inflate(void)1049 void test_nghttp2_hd_deflate_inflate(void) {
1050 nghttp2_hd_deflater deflater;
1051 nghttp2_hd_inflater inflater;
1052 nghttp2_nv nv1[] = {
1053 MAKE_NV(":status", "200 OK"),
1054 MAKE_NV("access-control-allow-origin", "*"),
1055 MAKE_NV("cache-control", "private, max-age=0, must-revalidate"),
1056 MAKE_NV("content-length", "76073"),
1057 MAKE_NV("content-type", "text/html"),
1058 MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1059 MAKE_NV("expires", "Sat, 27 Jul 2013 06:22:12 GMT"),
1060 MAKE_NV("server", "Apache"),
1061 MAKE_NV("vary", "foobar"),
1062 MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1063 MAKE_NV("x-cache", "MISS from alphabravo"),
1064 MAKE_NV("x-cache-action", "MISS"),
1065 MAKE_NV("x-cache-age", "0"),
1066 MAKE_NV("x-cache-lookup", "MISS from alphabravo:3128"),
1067 MAKE_NV("x-lb-nocache", "true"),
1068 };
1069 nghttp2_nv nv2[] = {
1070 MAKE_NV(":status", "304 Not Modified"),
1071 MAKE_NV("age", "0"),
1072 MAKE_NV("cache-control", "max-age=56682045"),
1073 MAKE_NV("content-type", "text/css"),
1074 MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1075 MAKE_NV("expires", "Thu, 14 May 2015 07:22:57 GMT"),
1076 MAKE_NV("last-modified", "Tue, 14 May 2013 07:22:15 GMT"),
1077 MAKE_NV("vary", "Accept-Encoding"),
1078 MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1079 MAKE_NV("x-cache", "HIT from alphabravo"),
1080 MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128")};
1081 nghttp2_nv nv3[] = {
1082 MAKE_NV(":status", "304 Not Modified"),
1083 MAKE_NV("age", "0"),
1084 MAKE_NV("cache-control", "max-age=56682072"),
1085 MAKE_NV("content-type", "text/css"),
1086 MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1087 MAKE_NV("expires", "Thu, 14 May 2015 07:23:24 GMT"),
1088 MAKE_NV("last-modified", "Tue, 14 May 2013 07:22:13 GMT"),
1089 MAKE_NV("vary", "Accept-Encoding"),
1090 MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1091 MAKE_NV("x-cache", "HIT from alphabravo"),
1092 MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
1093 };
1094 nghttp2_nv nv4[] = {
1095 MAKE_NV(":status", "304 Not Modified"),
1096 MAKE_NV("age", "0"),
1097 MAKE_NV("cache-control", "max-age=56682022"),
1098 MAKE_NV("content-type", "text/css"),
1099 MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1100 MAKE_NV("expires", "Thu, 14 May 2015 07:22:34 GMT"),
1101 MAKE_NV("last-modified", "Tue, 14 May 2013 07:22:14 GMT"),
1102 MAKE_NV("vary", "Accept-Encoding"),
1103 MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1104 MAKE_NV("x-cache", "HIT from alphabravo"),
1105 MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
1106 };
1107 nghttp2_nv nv5[] = {
1108 MAKE_NV(":status", "304 Not Modified"),
1109 MAKE_NV("age", "0"),
1110 MAKE_NV("cache-control", "max-age=4461139"),
1111 MAKE_NV("content-type", "application/x-javascript"),
1112 MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1113 MAKE_NV("expires", "Mon, 16 Sep 2013 21:34:31 GMT"),
1114 MAKE_NV("last-modified", "Thu, 05 May 2011 09:15:59 GMT"),
1115 MAKE_NV("vary", "Accept-Encoding"),
1116 MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1117 MAKE_NV("x-cache", "HIT from alphabravo"),
1118 MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
1119 };
1120 nghttp2_nv nv6[] = {
1121 MAKE_NV(":status", "304 Not Modified"),
1122 MAKE_NV("age", "0"),
1123 MAKE_NV("cache-control", "max-age=18645951"),
1124 MAKE_NV("content-type", "application/x-javascript"),
1125 MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1126 MAKE_NV("expires", "Fri, 28 Feb 2014 01:48:03 GMT"),
1127 MAKE_NV("last-modified", "Tue, 12 Jul 2011 16:02:59 GMT"),
1128 MAKE_NV("vary", "Accept-Encoding"),
1129 MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1130 MAKE_NV("x-cache", "HIT from alphabravo"),
1131 MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
1132 };
1133 nghttp2_nv nv7[] = {
1134 MAKE_NV(":status", "304 Not Modified"),
1135 MAKE_NV("age", "0"),
1136 MAKE_NV("cache-control", "max-age=31536000"),
1137 MAKE_NV("content-type", "application/javascript"),
1138 MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1139 MAKE_NV("etag", "\"6807-4dc5b54e0dcc0\""),
1140 MAKE_NV("expires", "Wed, 21 May 2014 08:32:17 GMT"),
1141 MAKE_NV("last-modified", "Fri, 10 May 2013 11:18:51 GMT"),
1142 MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1143 MAKE_NV("x-cache", "HIT from alphabravo"),
1144 MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
1145 };
1146 nghttp2_nv nv8[] = {
1147 MAKE_NV(":status", "304 Not Modified"),
1148 MAKE_NV("age", "0"),
1149 MAKE_NV("cache-control", "max-age=31536000"),
1150 MAKE_NV("content-type", "application/javascript"),
1151 MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1152 MAKE_NV("etag", "\"41c6-4de7d28585b00\""),
1153 MAKE_NV("expires", "Thu, 12 Jun 2014 10:00:58 GMT"),
1154 MAKE_NV("last-modified", "Thu, 06 Jun 2013 14:30:36 GMT"),
1155 MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1156 MAKE_NV("x-cache", "HIT from alphabravo"),
1157 MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
1158 };
1159 nghttp2_nv nv9[] = {
1160 MAKE_NV(":status", "304 Not Modified"),
1161 MAKE_NV("age", "0"),
1162 MAKE_NV("cache-control", "max-age=31536000"),
1163 MAKE_NV("content-type", "application/javascript"),
1164 MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1165 MAKE_NV("etag", "\"19d6e-4dc5b35a541c0\""),
1166 MAKE_NV("expires", "Wed, 21 May 2014 08:32:18 GMT"),
1167 MAKE_NV("last-modified", "Fri, 10 May 2013 11:10:07 GMT"),
1168 MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1169 MAKE_NV("x-cache", "HIT from alphabravo"),
1170 MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
1171 };
1172 nghttp2_nv nv10[] = {
1173 MAKE_NV(":status", "304 Not Modified"),
1174 MAKE_NV("age", "0"),
1175 MAKE_NV("cache-control", "max-age=56682045"),
1176 MAKE_NV("content-type", "text/css"),
1177 MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1178 MAKE_NV("expires", "Thu, 14 May 2015 07:22:57 GMT"),
1179 MAKE_NV("last-modified", "Tue, 14 May 2013 07:21:53 GMT"),
1180 MAKE_NV("vary", "Accept-Encoding"),
1181 MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1182 MAKE_NV("x-cache", "HIT from alphabravo"),
1183 MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
1184 };
1185 nghttp2_mem *mem;
1186
1187 mem = nghttp2_mem_default();
1188
1189 nghttp2_hd_deflate_init(&deflater, mem);
1190 nghttp2_hd_inflate_init(&inflater, mem);
1191
1192 check_deflate_inflate(&deflater, &inflater, nv1, ARRLEN(nv1), mem);
1193 check_deflate_inflate(&deflater, &inflater, nv2, ARRLEN(nv2), mem);
1194 check_deflate_inflate(&deflater, &inflater, nv3, ARRLEN(nv3), mem);
1195 check_deflate_inflate(&deflater, &inflater, nv4, ARRLEN(nv4), mem);
1196 check_deflate_inflate(&deflater, &inflater, nv5, ARRLEN(nv5), mem);
1197 check_deflate_inflate(&deflater, &inflater, nv6, ARRLEN(nv6), mem);
1198 check_deflate_inflate(&deflater, &inflater, nv7, ARRLEN(nv7), mem);
1199 check_deflate_inflate(&deflater, &inflater, nv8, ARRLEN(nv8), mem);
1200 check_deflate_inflate(&deflater, &inflater, nv9, ARRLEN(nv9), mem);
1201 check_deflate_inflate(&deflater, &inflater, nv10, ARRLEN(nv10), mem);
1202
1203 nghttp2_hd_inflate_free(&inflater);
1204 nghttp2_hd_deflate_free(&deflater);
1205 }
1206
test_nghttp2_hd_no_index(void)1207 void test_nghttp2_hd_no_index(void) {
1208 nghttp2_hd_deflater deflater;
1209 nghttp2_hd_inflater inflater;
1210 nghttp2_bufs bufs;
1211 nghttp2_ssize blocklen;
1212 nghttp2_nv nva[] = {
1213 MAKE_NV(":method", "GET"), MAKE_NV(":method", "POST"),
1214 MAKE_NV(":path", "/foo"), MAKE_NV("version", "HTTP/1.1"),
1215 MAKE_NV(":method", "GET"),
1216 };
1217 size_t i;
1218 nva_out out;
1219 int rv;
1220 nghttp2_mem *mem;
1221
1222 mem = nghttp2_mem_default();
1223
1224 /* 1st :method: GET can be indexable, last one is not */
1225 for (i = 1; i < ARRLEN(nva); ++i) {
1226 nva[i].flags = NGHTTP2_NV_FLAG_NO_INDEX;
1227 }
1228
1229 frame_pack_bufs_init(&bufs);
1230
1231 nva_out_init(&out);
1232
1233 nghttp2_hd_deflate_init(&deflater, mem);
1234 nghttp2_hd_inflate_init(&inflater, mem);
1235
1236 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, ARRLEN(nva));
1237 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
1238
1239 assert_int(0, ==, rv);
1240 assert_ptrdiff(0, <, blocklen);
1241 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
1242
1243 assert_size(ARRLEN(nva), ==, out.nvlen);
1244 assert_nv_equal(nva, out.nva, ARRLEN(nva), mem);
1245
1246 assert_uint8(NGHTTP2_NV_FLAG_NONE, ==, out.nva[0].flags);
1247 for (i = 1; i < ARRLEN(nva); ++i) {
1248 assert_uint8(NGHTTP2_NV_FLAG_NO_INDEX, ==, out.nva[i].flags);
1249 }
1250
1251 nva_out_reset(&out, mem);
1252
1253 nghttp2_bufs_free(&bufs);
1254 nghttp2_hd_inflate_free(&inflater);
1255 nghttp2_hd_deflate_free(&deflater);
1256 }
1257
test_nghttp2_hd_deflate_bound(void)1258 void test_nghttp2_hd_deflate_bound(void) {
1259 nghttp2_hd_deflater deflater;
1260 nghttp2_nv nva[] = {MAKE_NV(":method", "GET"), MAKE_NV("alpha", "bravo")};
1261 nghttp2_bufs bufs;
1262 size_t bound, bound2;
1263 nghttp2_mem *mem;
1264
1265 mem = nghttp2_mem_default();
1266 frame_pack_bufs_init(&bufs);
1267
1268 nghttp2_hd_deflate_init(&deflater, mem);
1269
1270 bound = nghttp2_hd_deflate_bound(&deflater, nva, ARRLEN(nva));
1271
1272 assert_size(12 + 6 * 2 * 2 + nva[0].namelen + nva[0].valuelen +
1273 nva[1].namelen + nva[1].valuelen,
1274 ==, bound);
1275
1276 nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, ARRLEN(nva));
1277
1278 assert_size((size_t)nghttp2_bufs_len(&bufs), <, bound);
1279
1280 bound2 = nghttp2_hd_deflate_bound(&deflater, nva, ARRLEN(nva));
1281
1282 assert_size(bound, ==, bound2);
1283
1284 nghttp2_bufs_free(&bufs);
1285 nghttp2_hd_deflate_free(&deflater);
1286 }
1287
test_nghttp2_hd_public_api(void)1288 void test_nghttp2_hd_public_api(void) {
1289 nghttp2_hd_deflater *deflater;
1290 nghttp2_hd_inflater *inflater;
1291 nghttp2_nv nva[] = {MAKE_NV("alpha", "bravo"), MAKE_NV("charlie", "delta")};
1292 uint8_t buf[4096];
1293 size_t buflen;
1294 nghttp2_ssize blocklen;
1295 nghttp2_bufs bufs;
1296 nghttp2_mem *mem;
1297
1298 mem = nghttp2_mem_default();
1299
1300 assert_int(0, ==, nghttp2_hd_deflate_new(&deflater, 4096));
1301 assert_int(0, ==, nghttp2_hd_inflate_new(&inflater));
1302
1303 buflen = nghttp2_hd_deflate_bound(deflater, nva, ARRLEN(nva));
1304
1305 blocklen = nghttp2_hd_deflate_hd2(deflater, buf, buflen, nva, ARRLEN(nva));
1306
1307 assert_ptrdiff(0, <, blocklen);
1308
1309 nghttp2_bufs_wrap_init(&bufs, buf, (size_t)blocklen, mem);
1310 bufs.head->buf.last += blocklen;
1311
1312 assert_ptrdiff(blocklen, ==, inflate_hd(inflater, NULL, &bufs, 0, mem));
1313
1314 nghttp2_bufs_wrap_free(&bufs);
1315
1316 nghttp2_hd_inflate_del(inflater);
1317 nghttp2_hd_deflate_del(deflater);
1318
1319 /* See NGHTTP2_ERR_INSUFF_BUFSIZE */
1320 assert_int(0, ==, nghttp2_hd_deflate_new(&deflater, 4096));
1321
1322 blocklen = nghttp2_hd_deflate_hd2(deflater, buf, (size_t)(blocklen - 1), nva,
1323 ARRLEN(nva));
1324
1325 assert_ptrdiff(NGHTTP2_ERR_INSUFF_BUFSIZE, ==, blocklen);
1326
1327 nghttp2_hd_deflate_del(deflater);
1328 }
1329
test_nghttp2_hd_deflate_hd_vec(void)1330 void test_nghttp2_hd_deflate_hd_vec(void) {
1331 nghttp2_hd_deflater *deflater;
1332 nghttp2_hd_inflater *inflater;
1333 nghttp2_nv nva[] = {
1334 MAKE_NV(":method", "PUT"),
1335 MAKE_NV(":scheme", "https"),
1336 MAKE_NV(":authority", "localhost:3000"),
1337 MAKE_NV(":path", "/usr/foo/alpha/bravo"),
1338 MAKE_NV("content-type", "image/png"),
1339 MAKE_NV("content-length", "1000000007"),
1340 };
1341 uint8_t buf[4096];
1342 nghttp2_ssize blocklen;
1343 nghttp2_mem *mem;
1344 nghttp2_vec vec[256];
1345 size_t buflen;
1346 nghttp2_bufs bufs;
1347 nva_out out;
1348 size_t i;
1349
1350 mem = nghttp2_mem_default();
1351
1352 nva_out_init(&out);
1353
1354 nghttp2_hd_deflate_new(&deflater, 4096);
1355 nghttp2_hd_inflate_new(&inflater);
1356
1357 buflen = nghttp2_hd_deflate_bound(deflater, nva, ARRLEN(nva));
1358
1359 vec[0].base = &buf[0];
1360 vec[0].len = buflen / 2;
1361 vec[1].base = &buf[buflen / 2];
1362 vec[1].len = buflen / 2;
1363
1364 blocklen = nghttp2_hd_deflate_hd_vec2(deflater, vec, 2, nva, ARRLEN(nva));
1365
1366 assert_ptrdiff(0, <, blocklen);
1367
1368 nghttp2_bufs_wrap_init(&bufs, buf, (size_t)blocklen, mem);
1369 bufs.head->buf.last += blocklen;
1370
1371 assert_ptrdiff(blocklen, ==, inflate_hd(inflater, &out, &bufs, 0, mem));
1372
1373 assert_size(ARRLEN(nva), ==, out.nvlen);
1374 assert_nv_equal(nva, out.nva, ARRLEN(nva), mem);
1375
1376 nghttp2_bufs_wrap_free(&bufs);
1377
1378 nghttp2_hd_inflate_del(inflater);
1379 nghttp2_hd_deflate_del(deflater);
1380 nva_out_reset(&out, mem);
1381
1382 /* check the case when veclen is 0 */
1383 nghttp2_hd_deflate_new(&deflater, 4096);
1384 nghttp2_hd_inflate_new(&inflater);
1385
1386 blocklen = nghttp2_hd_deflate_hd_vec2(deflater, NULL, 0, nva, ARRLEN(nva));
1387
1388 assert_ptrdiff(NGHTTP2_ERR_INSUFF_BUFSIZE, ==, blocklen);
1389
1390 nghttp2_hd_inflate_del(inflater);
1391 nghttp2_hd_deflate_del(deflater);
1392
1393 /* check the case when chunk length is 0 */
1394 vec[0].base = NULL;
1395 vec[0].len = 0;
1396 vec[1].base = NULL;
1397 vec[1].len = 0;
1398
1399 nghttp2_hd_deflate_new(&deflater, 4096);
1400 nghttp2_hd_inflate_new(&inflater);
1401
1402 blocklen = nghttp2_hd_deflate_hd_vec2(deflater, vec, 2, nva, ARRLEN(nva));
1403
1404 assert_ptrdiff(NGHTTP2_ERR_INSUFF_BUFSIZE, ==, blocklen);
1405
1406 nghttp2_hd_inflate_del(inflater);
1407 nghttp2_hd_deflate_del(deflater);
1408
1409 /* check the case where chunk size differs in each chunk */
1410 nghttp2_hd_deflate_new(&deflater, 4096);
1411 nghttp2_hd_inflate_new(&inflater);
1412
1413 buflen = nghttp2_hd_deflate_bound(deflater, nva, ARRLEN(nva));
1414
1415 vec[0].base = &buf[0];
1416 vec[0].len = buflen / 2;
1417 vec[1].base = &buf[buflen / 2];
1418 vec[1].len = (buflen / 2) + 1;
1419
1420 blocklen = nghttp2_hd_deflate_hd_vec2(deflater, vec, 2, nva, ARRLEN(nva));
1421
1422 assert_ptrdiff(0, <, blocklen);
1423
1424 nghttp2_bufs_wrap_init(&bufs, buf, (size_t)blocklen, mem);
1425 bufs.head->buf.last += blocklen;
1426
1427 assert_ptrdiff(blocklen, ==, inflate_hd(inflater, &out, &bufs, 0, mem));
1428 assert_size(ARRLEN(nva), ==, out.nvlen);
1429 assert_nv_equal(nva, out.nva, ARRLEN(nva), mem);
1430
1431 nghttp2_bufs_wrap_free(&bufs);
1432
1433 nghttp2_hd_inflate_del(inflater);
1434 nghttp2_hd_deflate_del(deflater);
1435 nva_out_reset(&out, mem);
1436
1437 /* check the case where chunk size is 1 */
1438 nghttp2_hd_deflate_new(&deflater, 4096);
1439 nghttp2_hd_inflate_new(&inflater);
1440
1441 buflen = nghttp2_hd_deflate_bound(deflater, nva, ARRLEN(nva));
1442
1443 assert(buflen <= ARRLEN(vec));
1444
1445 for (i = 0; i < buflen; ++i) {
1446 vec[i].base = &buf[i];
1447 vec[i].len = 1;
1448 }
1449
1450 blocklen =
1451 nghttp2_hd_deflate_hd_vec2(deflater, vec, buflen, nva, ARRLEN(nva));
1452
1453 assert_ptrdiff(0, <, blocklen);
1454
1455 nghttp2_bufs_wrap_init(&bufs, buf, (size_t)blocklen, mem);
1456 bufs.head->buf.last += blocklen;
1457
1458 assert_ptrdiff(blocklen, ==, inflate_hd(inflater, &out, &bufs, 0, mem));
1459 assert_size(ARRLEN(nva), ==, out.nvlen);
1460 assert_nv_equal(nva, out.nva, ARRLEN(nva), mem);
1461
1462 nghttp2_bufs_wrap_free(&bufs);
1463
1464 nghttp2_hd_inflate_del(inflater);
1465 nghttp2_hd_deflate_del(deflater);
1466 nva_out_reset(&out, mem);
1467 }
1468
encode_length(uint8_t * buf,uint64_t n,size_t prefix)1469 static size_t encode_length(uint8_t *buf, uint64_t n, size_t prefix) {
1470 size_t k = (size_t)((1 << prefix) - 1);
1471 size_t len = 0;
1472 *buf = (uint8_t)(*buf & ~k);
1473 if (n >= k) {
1474 *buf = (uint8_t)(*buf | k);
1475 ++buf;
1476 n -= k;
1477 ++len;
1478 } else {
1479 *buf = (uint8_t)(*buf | n);
1480 ++buf;
1481 return 1;
1482 }
1483 do {
1484 ++len;
1485 if (n >= 128) {
1486 *buf = (uint8_t)((1 << 7) | (n & 0x7f));
1487 ++buf;
1488 n >>= 7;
1489 } else {
1490 *buf++ = (uint8_t)n;
1491 break;
1492 }
1493 } while (n);
1494 return len;
1495 }
1496
test_nghttp2_hd_decode_length(void)1497 void test_nghttp2_hd_decode_length(void) {
1498 uint32_t out;
1499 size_t shift;
1500 int fin;
1501 uint8_t buf[16];
1502 uint8_t *bufp;
1503 size_t len;
1504 nghttp2_ssize rv;
1505 size_t i;
1506
1507 memset(buf, 0, sizeof(buf));
1508 len = encode_length(buf, UINT32_MAX, 7);
1509
1510 rv = nghttp2_hd_decode_length(&out, &shift, &fin, 0, 0, buf, buf + len, 7);
1511
1512 assert_ptrdiff((nghttp2_ssize)len, ==, rv);
1513 assert_true(fin);
1514 assert_uint32(UINT32_MAX, ==, out);
1515
1516 /* Make sure that we can decode integer if we feed 1 byte at a
1517 time */
1518 out = 0;
1519 shift = 0;
1520 fin = 0;
1521 bufp = buf;
1522
1523 for (i = 0; i < len; ++i, ++bufp) {
1524 rv = nghttp2_hd_decode_length(&out, &shift, &fin, out, shift, bufp,
1525 bufp + 1, 7);
1526
1527 assert_ptrdiff(1, ==, rv);
1528
1529 if (fin) {
1530 break;
1531 }
1532 }
1533
1534 assert_size(len - 1, ==, i);
1535 assert_true(fin);
1536 assert_size(UINT32_MAX, ==, out);
1537
1538 /* Check overflow case */
1539 memset(buf, 0, sizeof(buf));
1540 len = encode_length(buf, 1ll << 32, 7);
1541
1542 rv = nghttp2_hd_decode_length(&out, &shift, &fin, 0, 0, buf, buf + len, 7);
1543
1544 assert_ptrdiff(-1, ==, rv);
1545
1546 /* Check the case that shift goes beyond 32 bits */
1547 buf[0] = 255;
1548 buf[1] = 128;
1549 buf[2] = 128;
1550 buf[3] = 128;
1551 buf[4] = 128;
1552 buf[5] = 128;
1553 buf[6] = 1;
1554
1555 rv = nghttp2_hd_decode_length(&out, &shift, &fin, 0, 0, buf, buf + 7, 8);
1556
1557 assert_ptrdiff(-1, ==, rv);
1558 }
1559
test_nghttp2_hd_huff_encode(void)1560 void test_nghttp2_hd_huff_encode(void) {
1561 int rv;
1562 nghttp2_ssize len;
1563 nghttp2_buf outbuf;
1564 nghttp2_bufs bufs;
1565 nghttp2_hd_huff_decode_context ctx;
1566 const uint8_t t1[] = {22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11,
1567 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
1568 uint8_t b[256];
1569
1570 nghttp2_buf_wrap_init(&outbuf, b, sizeof(b));
1571 frame_pack_bufs_init(&bufs);
1572
1573 rv = nghttp2_hd_huff_encode(&bufs, t1, sizeof(t1));
1574
1575 assert_int(0, ==, rv);
1576
1577 nghttp2_hd_huff_decode_context_init(&ctx);
1578
1579 len = nghttp2_hd_huff_decode(&ctx, &outbuf, bufs.cur->buf.pos,
1580 nghttp2_bufs_len(&bufs), 1);
1581
1582 assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, len);
1583 assert_size(sizeof(t1), ==, nghttp2_buf_len(&outbuf));
1584
1585 assert_memory_equal(sizeof(t1), t1, outbuf.pos);
1586
1587 nghttp2_bufs_free(&bufs);
1588 }
1589
test_nghttp2_hd_huff_decode(void)1590 void test_nghttp2_hd_huff_decode(void) {
1591 const uint8_t e[] = {0x1f, 0xff, 0xff, 0xff, 0xff, 0xff};
1592 nghttp2_hd_huff_decode_context ctx;
1593 nghttp2_buf outbuf;
1594 uint8_t b[256];
1595 nghttp2_ssize len;
1596
1597 nghttp2_buf_wrap_init(&outbuf, b, sizeof(b));
1598 nghttp2_hd_huff_decode_context_init(&ctx);
1599 len = nghttp2_hd_huff_decode(&ctx, &outbuf, e, 1, 1);
1600
1601 assert_ptrdiff(1, ==, len);
1602 assert_memory_equal(1, "a", outbuf.pos);
1603
1604 /* Premature sequence must elicit decoding error */
1605 nghttp2_buf_wrap_init(&outbuf, b, sizeof(b));
1606 nghttp2_hd_huff_decode_context_init(&ctx);
1607 len = nghttp2_hd_huff_decode(&ctx, &outbuf, e, 2, 1);
1608
1609 assert_ptrdiff(NGHTTP2_ERR_HEADER_COMP, ==, len);
1610
1611 /* Fully decoding EOS is error */
1612 nghttp2_buf_wrap_init(&outbuf, b, sizeof(b));
1613 nghttp2_hd_huff_decode_context_init(&ctx);
1614 len = nghttp2_hd_huff_decode(&ctx, &outbuf, e, 2, 6);
1615
1616 assert_ptrdiff(NGHTTP2_ERR_HEADER_COMP, ==, len);
1617
1618 /* Check failure state */
1619 nghttp2_buf_wrap_init(&outbuf, b, sizeof(b));
1620 nghttp2_hd_huff_decode_context_init(&ctx);
1621 len = nghttp2_hd_huff_decode(&ctx, &outbuf, e, 5, 0);
1622
1623 assert_ptrdiff(5, ==, len);
1624 assert_true(nghttp2_hd_huff_decode_failure_state(&ctx));
1625 }
1626