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(&inflater, NGHTTP2_STATIC_TABLE_LENGTH +
334 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, ==, nghttp2_hd_emit_newname_block(&bufs, &nv, NGHTTP2_HD_WITH_INDEXING));
457
458 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
459
460 assert_ptrdiff(0, <, blocklen);
461 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
462
463 assert_size(1, ==, out.nvlen);
464 assert_nv_equal(&nv, out.nva, 1, mem);
465 assert_size(1, ==, inflater.ctx.hd_table.len);
466 assert_nv_equal(
467 &nv,
468 nghttp2_hd_inflate_get_table_entry(&inflater, NGHTTP2_STATIC_TABLE_LENGTH +
469 inflater.ctx.hd_table.len),
470 1, mem);
471
472 nva_out_reset(&out, mem);
473 nghttp2_bufs_free(&bufs);
474 nghttp2_hd_inflate_free(&inflater);
475 }
476
test_nghttp2_hd_inflate_clearall_inc(void)477 void test_nghttp2_hd_inflate_clearall_inc(void) {
478 nghttp2_hd_inflater inflater;
479 nghttp2_bufs bufs;
480 nghttp2_ssize blocklen;
481 nghttp2_nv nv;
482 uint8_t value[4061];
483 nva_out out;
484 nghttp2_mem *mem;
485
486 mem = nghttp2_mem_default();
487 bufs_large_init(&bufs, 8192);
488
489 nva_out_init(&out);
490 /* Total 4097 bytes space required to hold this entry */
491 nv.name = (uint8_t *)"alpha";
492 nv.namelen = strlen((char *)nv.name);
493 memset(value, '0', sizeof(value));
494 value[sizeof(value) - 1] = '\0';
495 nv.value = value;
496 nv.valuelen = sizeof(value) - 1;
497
498 nv.flags = NGHTTP2_NV_FLAG_NONE;
499
500 nghttp2_hd_inflate_init(&inflater, mem);
501
502 assert_int(
503 0, ==, nghttp2_hd_emit_newname_block(&bufs, &nv, NGHTTP2_HD_WITH_INDEXING));
504
505 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
506
507 assert_ptrdiff(0, <, blocklen);
508 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
509
510 assert_size(1, ==, out.nvlen);
511 assert_nv_equal(&nv, out.nva, 1, mem);
512 assert_size(0, ==, inflater.ctx.hd_table.len);
513
514 nva_out_reset(&out, mem);
515
516 /* Do it again */
517 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
518
519 assert_size(1, ==, out.nvlen);
520 assert_nv_equal(&nv, out.nva, 1, mem);
521 assert_size(0, ==, inflater.ctx.hd_table.len);
522
523 nva_out_reset(&out, mem);
524 nghttp2_bufs_reset(&bufs);
525
526 /* This time, 4096 bytes space required, which is just fits in the
527 header table */
528 nv.valuelen = sizeof(value) - 2;
529
530 assert_int(
531 0, ==, nghttp2_hd_emit_newname_block(&bufs, &nv, NGHTTP2_HD_WITH_INDEXING));
532
533 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
534
535 assert_ptrdiff(0, <, blocklen);
536 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
537
538 assert_size(1, ==, out.nvlen);
539 assert_nv_equal(&nv, out.nva, 1, mem);
540 assert_size(1, ==, inflater.ctx.hd_table.len);
541
542 nva_out_reset(&out, mem);
543 nghttp2_bufs_reset(&bufs);
544
545 nghttp2_bufs_free(&bufs);
546 nghttp2_hd_inflate_free(&inflater);
547 }
548
test_nghttp2_hd_inflate_zero_length_huffman(void)549 void test_nghttp2_hd_inflate_zero_length_huffman(void) {
550 nghttp2_hd_inflater inflater;
551 nghttp2_bufs bufs;
552 /* Literal header without indexing - new name */
553 uint8_t data[] = {0x40, 0x01, 0x78 /* 'x' */, 0x80};
554 nva_out out;
555 nghttp2_mem *mem;
556
557 mem = nghttp2_mem_default();
558 frame_pack_bufs_init(&bufs);
559
560 nva_out_init(&out);
561
562 nghttp2_bufs_add(&bufs, data, sizeof(data));
563
564 /* /\* Literal header without indexing - new name *\/ */
565 /* ptr[0] = 0x40; */
566 /* ptr[1] = 1; */
567 /* ptr[2] = 'x'; */
568 /* ptr[3] = 0x80; */
569
570 nghttp2_hd_inflate_init(&inflater, mem);
571 assert_ptrdiff(4, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
572
573 assert_size(1, ==, out.nvlen);
574 assert_size(1, ==, out.nva[0].namelen);
575 assert_uint8('x', ==, out.nva[0].name[0]);
576 assert_null(out.nva[0].value);
577 assert_size(0, ==, out.nva[0].valuelen);
578
579 nva_out_reset(&out, mem);
580 nghttp2_bufs_free(&bufs);
581 nghttp2_hd_inflate_free(&inflater);
582 }
583
test_nghttp2_hd_inflate_expect_table_size_update(void)584 void test_nghttp2_hd_inflate_expect_table_size_update(void) {
585 nghttp2_hd_inflater inflater;
586 nghttp2_bufs bufs;
587 nghttp2_mem *mem;
588 /* Indexed Header: :method: GET */
589 uint8_t data[] = {0x82};
590 nva_out out;
591
592 mem = nghttp2_mem_default();
593 frame_pack_bufs_init(&bufs);
594 nva_out_init(&out);
595
596 nghttp2_bufs_add(&bufs, data, sizeof(data));
597 nghttp2_hd_inflate_init(&inflater, mem);
598 /* This will make inflater require table size update in the next
599 inflation. */
600 nghttp2_hd_inflate_change_table_size(&inflater, 4095);
601 nghttp2_hd_inflate_change_table_size(&inflater, 4096);
602 assert_ptrdiff(NGHTTP2_ERR_HEADER_COMP, ==,
603 inflate_hd(&inflater, &out, &bufs, 0, mem));
604
605 nva_out_reset(&out, mem);
606 nghttp2_hd_inflate_free(&inflater);
607
608 /* This does not require for encoder to emit table size update since
609 * size is not changed. */
610 nghttp2_hd_inflate_init(&inflater, mem);
611 nghttp2_hd_inflate_change_table_size(&inflater, 4096);
612 assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==,
613 inflate_hd(&inflater, &out, &bufs, 0, mem));
614
615 nva_out_reset(&out, mem);
616 nghttp2_hd_inflate_free(&inflater);
617
618 /* This does not require for encodre to emit table size update since
619 new size is larger than current size. */
620 nghttp2_hd_inflate_init(&inflater, mem);
621 nghttp2_hd_inflate_change_table_size(&inflater, 4097);
622 assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==,
623 inflate_hd(&inflater, &out, &bufs, 0, mem));
624
625 nva_out_reset(&out, mem);
626 nghttp2_hd_inflate_free(&inflater);
627
628 /* Received table size is strictly larger than minimum table size */
629 nghttp2_hd_inflate_init(&inflater, mem);
630 nghttp2_hd_inflate_change_table_size(&inflater, 111);
631 nghttp2_hd_inflate_change_table_size(&inflater, 4096);
632
633 nghttp2_bufs_reset(&bufs);
634 nghttp2_hd_emit_table_size(&bufs, 112);
635
636 assert_ptrdiff(NGHTTP2_ERR_HEADER_COMP, ==,
637 inflate_hd(&inflater, &out, &bufs, 0, mem));
638
639 nva_out_reset(&out, mem);
640 nghttp2_hd_inflate_free(&inflater);
641
642 /* Receiving 2 table size updates, min and last value */
643 nghttp2_hd_inflate_init(&inflater, mem);
644 nghttp2_hd_inflate_change_table_size(&inflater, 111);
645 nghttp2_hd_inflate_change_table_size(&inflater, 4096);
646
647 nghttp2_bufs_reset(&bufs);
648 nghttp2_hd_emit_table_size(&bufs, 111);
649 nghttp2_hd_emit_table_size(&bufs, 4096);
650
651 assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==,
652 inflate_hd(&inflater, &out, &bufs, 0, mem));
653
654 nva_out_reset(&out, mem);
655 nghttp2_hd_inflate_free(&inflater);
656
657 /* 2nd update is larger than last value */
658 nghttp2_hd_inflate_init(&inflater, mem);
659 nghttp2_hd_inflate_change_table_size(&inflater, 111);
660 nghttp2_hd_inflate_change_table_size(&inflater, 4095);
661
662 nghttp2_bufs_reset(&bufs);
663 nghttp2_hd_emit_table_size(&bufs, 111);
664 nghttp2_hd_emit_table_size(&bufs, 4096);
665
666 assert_ptrdiff(NGHTTP2_ERR_HEADER_COMP, ==,
667 inflate_hd(&inflater, &out, &bufs, 0, mem));
668
669 nva_out_reset(&out, mem);
670 nghttp2_hd_inflate_free(&inflater);
671
672 nghttp2_bufs_free(&bufs);
673 }
674
test_nghttp2_hd_inflate_unexpected_table_size_update(void)675 void test_nghttp2_hd_inflate_unexpected_table_size_update(void) {
676 nghttp2_hd_inflater inflater;
677 nghttp2_bufs bufs;
678 nghttp2_mem *mem;
679 /* Indexed Header: :method: GET, followed by table size update.
680 This violates RFC 7541. */
681 uint8_t data[] = {0x82, 0x20};
682 nva_out out;
683
684 mem = nghttp2_mem_default();
685 frame_pack_bufs_init(&bufs);
686 nva_out_init(&out);
687
688 nghttp2_bufs_add(&bufs, data, sizeof(data));
689 nghttp2_hd_inflate_init(&inflater, mem);
690 assert_ptrdiff(NGHTTP2_ERR_HEADER_COMP, ==,
691 inflate_hd(&inflater, &out, &bufs, 0, mem));
692
693 nva_out_reset(&out, mem);
694 nghttp2_bufs_free(&bufs);
695 nghttp2_hd_inflate_free(&inflater);
696 }
697
test_nghttp2_hd_ringbuf_reserve(void)698 void test_nghttp2_hd_ringbuf_reserve(void) {
699 nghttp2_hd_deflater deflater;
700 nghttp2_hd_inflater inflater;
701 nghttp2_nv nv;
702 nghttp2_bufs bufs;
703 nva_out out;
704 int i;
705 nghttp2_ssize rv;
706 nghttp2_ssize blocklen;
707 nghttp2_mem *mem;
708
709 mem = nghttp2_mem_default();
710 frame_pack_bufs_init(&bufs);
711 nva_out_init(&out);
712
713 nv.flags = NGHTTP2_NV_FLAG_NONE;
714 nv.name = (uint8_t *)"a";
715 nv.namelen = strlen((const char *)nv.name);
716 nv.valuelen = 4;
717 nv.value = mem->malloc(nv.valuelen + 1, NULL);
718 memset(nv.value, 0, nv.valuelen);
719
720 nghttp2_hd_deflate_init2(&deflater, 8000, mem);
721 nghttp2_hd_inflate_init(&inflater, mem);
722
723 nghttp2_hd_inflate_change_table_size(&inflater, 8000);
724 nghttp2_hd_deflate_change_table_size(&deflater, 8000);
725
726 for (i = 0; i < 150; ++i) {
727 memcpy(nv.value, &i, sizeof(i));
728 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, &nv, 1);
729 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
730
731 assert_ptrdiff(0, ==, rv);
732 assert_ptrdiff(0, <, blocklen);
733
734 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
735
736 assert_size(1, ==, out.nvlen);
737 assert_nv_equal(&nv, out.nva, 1, mem);
738
739 nva_out_reset(&out, mem);
740 nghttp2_bufs_reset(&bufs);
741 }
742
743 nghttp2_bufs_free(&bufs);
744 nghttp2_hd_inflate_free(&inflater);
745 nghttp2_hd_deflate_free(&deflater);
746
747 mem->free(nv.value, NULL);
748 }
749
test_nghttp2_hd_change_table_size(void)750 void test_nghttp2_hd_change_table_size(void) {
751 nghttp2_hd_deflater deflater;
752 nghttp2_hd_inflater inflater;
753 nghttp2_nv nva[] = {MAKE_NV("alpha", "bravo"), MAKE_NV("charlie", "delta")};
754 nghttp2_nv nva2[] = {MAKE_NV(":path", "/")};
755 nghttp2_bufs bufs;
756 int rv;
757 nva_out out;
758 nghttp2_ssize blocklen;
759 nghttp2_mem *mem;
760
761 mem = nghttp2_mem_default();
762 frame_pack_bufs_init(&bufs);
763
764 nva_out_init(&out);
765
766 nghttp2_hd_deflate_init(&deflater, mem);
767 nghttp2_hd_inflate_init(&inflater, mem);
768
769 /* inflater changes notifies 8000 max header table size */
770 assert_int(0, ==, nghttp2_hd_inflate_change_table_size(&inflater, 8000));
771 assert_int(0, ==, nghttp2_hd_deflate_change_table_size(&deflater, 8000));
772
773 assert_size(4096, ==, deflater.ctx.hd_table_bufsize_max);
774
775 assert_size(4096, ==, inflater.ctx.hd_table_bufsize_max);
776 assert_size(8000, ==, inflater.settings_hd_table_bufsize_max);
777
778 /* This will emit encoding context update with header table size 4096 */
779 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
780 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
781
782 assert_int(0, ==, rv);
783 assert_ptrdiff(0, <, blocklen);
784 assert_size(2, ==, deflater.ctx.hd_table.len);
785 assert_size(63, ==, nghttp2_hd_deflate_get_num_table_entries(&deflater));
786 assert_size(4096, ==, deflater.ctx.hd_table_bufsize_max);
787
788 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
789 assert_size(2, ==, inflater.ctx.hd_table.len);
790 assert_size(63, ==, nghttp2_hd_inflate_get_num_table_entries(&inflater));
791 assert_size(4096, ==, inflater.ctx.hd_table_bufsize_max);
792 assert_size(8000, ==, inflater.settings_hd_table_bufsize_max);
793
794 nva_out_reset(&out, mem);
795 nghttp2_bufs_reset(&bufs);
796
797 /* inflater changes header table size to 1024 */
798 assert_int(0, ==, nghttp2_hd_inflate_change_table_size(&inflater, 1024));
799 assert_int(0, ==, nghttp2_hd_deflate_change_table_size(&deflater, 1024));
800
801 assert_size(1024, ==, deflater.ctx.hd_table_bufsize_max);
802
803 assert_size(1024, ==, inflater.ctx.hd_table_bufsize_max);
804 assert_size(1024, ==, inflater.settings_hd_table_bufsize_max);
805
806 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
807 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
808
809 assert_int(0, ==, rv);
810 assert_ptrdiff(0, <, blocklen);
811 assert_size(2, ==, deflater.ctx.hd_table.len);
812 assert_size(63, ==, nghttp2_hd_deflate_get_num_table_entries(&deflater));
813 assert_size(1024, ==, deflater.ctx.hd_table_bufsize_max);
814
815 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
816 assert_size(2, ==, inflater.ctx.hd_table.len);
817 assert_size(63, ==, nghttp2_hd_inflate_get_num_table_entries(&inflater));
818 assert_size(1024, ==, inflater.ctx.hd_table_bufsize_max);
819 assert_size(1024, ==, inflater.settings_hd_table_bufsize_max);
820
821 nva_out_reset(&out, mem);
822 nghttp2_bufs_reset(&bufs);
823
824 /* inflater changes header table size to 0 */
825 assert_int(0, ==, nghttp2_hd_inflate_change_table_size(&inflater, 0));
826 assert_int(0, ==, nghttp2_hd_deflate_change_table_size(&deflater, 0));
827
828 assert_size(0, ==, deflater.ctx.hd_table.len);
829 assert_size(61, ==, nghttp2_hd_deflate_get_num_table_entries(&deflater));
830 assert_size(0, ==, deflater.ctx.hd_table_bufsize_max);
831
832 assert_size(0, ==, inflater.ctx.hd_table.len);
833 assert_size(61, ==, nghttp2_hd_inflate_get_num_table_entries(&inflater));
834 assert_size(0, ==, inflater.ctx.hd_table_bufsize_max);
835 assert_size(0, ==, inflater.settings_hd_table_bufsize_max);
836
837 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
838 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
839
840 assert_int(0, ==, rv);
841 assert_ptrdiff(0, <, blocklen);
842 assert_size(0, ==, deflater.ctx.hd_table.len);
843 assert_size(61, ==, nghttp2_hd_deflate_get_num_table_entries(&deflater));
844 assert_size(0, ==, deflater.ctx.hd_table_bufsize_max);
845
846 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
847 assert_size(0, ==, inflater.ctx.hd_table.len);
848 assert_size(61, ==, nghttp2_hd_inflate_get_num_table_entries(&inflater));
849 assert_size(0, ==, inflater.ctx.hd_table_bufsize_max);
850 assert_size(0, ==, inflater.settings_hd_table_bufsize_max);
851
852 nva_out_reset(&out, mem);
853 nghttp2_bufs_reset(&bufs);
854
855 nghttp2_bufs_free(&bufs);
856 nghttp2_hd_inflate_free(&inflater);
857 nghttp2_hd_deflate_free(&deflater);
858
859 /* Check table buffer is expanded */
860 frame_pack_bufs_init(&bufs);
861
862 nghttp2_hd_deflate_init2(&deflater, 8192, mem);
863 nghttp2_hd_inflate_init(&inflater, mem);
864
865 /* First inflater changes header table size to 8000 */
866 assert_int(0, ==, nghttp2_hd_inflate_change_table_size(&inflater, 8000));
867 assert_int(0, ==, nghttp2_hd_deflate_change_table_size(&deflater, 8000));
868
869 assert_size(8000, ==, deflater.ctx.hd_table_bufsize_max);
870 assert_size(8000, ==,
871 nghttp2_hd_deflate_get_max_dynamic_table_size(&deflater));
872 assert_size(4096, ==, inflater.ctx.hd_table_bufsize_max);
873 assert_size(4096, ==,
874 nghttp2_hd_inflate_get_max_dynamic_table_size(&inflater));
875 assert_size(8000, ==, inflater.settings_hd_table_bufsize_max);
876
877 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
878 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
879
880 assert_int(0, ==, rv);
881 assert_ptrdiff(0, <, blocklen);
882 assert_size(2, ==, deflater.ctx.hd_table.len);
883 assert_size(8000, ==, deflater.ctx.hd_table_bufsize_max);
884
885 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
886 assert_size(2, ==, inflater.ctx.hd_table.len);
887 assert_size(8000, ==, inflater.ctx.hd_table_bufsize_max);
888 assert_size(8000, ==, inflater.settings_hd_table_bufsize_max);
889
890 nva_out_reset(&out, mem);
891 nghttp2_bufs_reset(&bufs);
892
893 assert_int(0, ==, nghttp2_hd_inflate_change_table_size(&inflater, 16383));
894 assert_int(0, ==, nghttp2_hd_deflate_change_table_size(&deflater, 16383));
895
896 assert_size(8192, ==, deflater.ctx.hd_table_bufsize_max);
897 assert_size(8192, ==,
898 nghttp2_hd_deflate_get_max_dynamic_table_size(&deflater));
899
900 assert_size(8000, ==, inflater.ctx.hd_table_bufsize_max);
901 assert_size(8000, ==,
902 nghttp2_hd_inflate_get_max_dynamic_table_size(&inflater));
903 assert_size(16383, ==, inflater.settings_hd_table_bufsize_max);
904
905 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
906 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
907
908 assert_int(0, ==, rv);
909 assert_ptrdiff(0, <, blocklen);
910 assert_size(2, ==, deflater.ctx.hd_table.len);
911 assert_size(8192, ==, deflater.ctx.hd_table_bufsize_max);
912
913 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
914 assert_size(2, ==, inflater.ctx.hd_table.len);
915 assert_size(8192, ==, inflater.ctx.hd_table_bufsize_max);
916 assert_size(16383, ==, inflater.settings_hd_table_bufsize_max);
917
918 nva_out_reset(&out, mem);
919 nghttp2_bufs_reset(&bufs);
920
921 /* Lastly, check the error condition */
922
923 rv = nghttp2_hd_emit_table_size(&bufs, 25600);
924 assert_int(0, ==, rv);
925 assert_ptrdiff(NGHTTP2_ERR_HEADER_COMP, ==,
926 inflate_hd(&inflater, &out, &bufs, 0, mem));
927
928 nva_out_reset(&out, mem);
929 nghttp2_bufs_reset(&bufs);
930
931 nghttp2_hd_inflate_free(&inflater);
932 nghttp2_hd_deflate_free(&deflater);
933
934 /* Check that encoder can handle the case where its allowable buffer
935 size is less than default size, 4096 */
936 nghttp2_hd_deflate_init2(&deflater, 1024, mem);
937 nghttp2_hd_inflate_init(&inflater, mem);
938
939 assert_size(1024, ==, deflater.ctx.hd_table_bufsize_max);
940
941 /* This emits context update with buffer size 1024 */
942 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
943 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
944
945 assert_int(0, ==, rv);
946 assert_ptrdiff(0, <, blocklen);
947 assert_size(2, ==, deflater.ctx.hd_table.len);
948 assert_size(1024, ==, deflater.ctx.hd_table_bufsize_max);
949
950 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
951 assert_size(2, ==, inflater.ctx.hd_table.len);
952 assert_size(1024, ==, inflater.ctx.hd_table_bufsize_max);
953 assert_size(4096, ==, inflater.settings_hd_table_bufsize_max);
954
955 nva_out_reset(&out, mem);
956 nghttp2_bufs_reset(&bufs);
957
958 nghttp2_hd_inflate_free(&inflater);
959 nghttp2_hd_deflate_free(&deflater);
960
961 /* Check that table size UINT32_MAX can be received */
962 nghttp2_hd_deflate_init2(&deflater, UINT32_MAX, mem);
963 nghttp2_hd_inflate_init(&inflater, mem);
964
965 assert_int(0, ==,
966 nghttp2_hd_inflate_change_table_size(&inflater, UINT32_MAX));
967 assert_int(0, ==,
968 nghttp2_hd_deflate_change_table_size(&deflater, UINT32_MAX));
969
970 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
971 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
972
973 assert_int(0, ==, rv);
974 assert_size(UINT32_MAX, ==, deflater.ctx.hd_table_bufsize_max);
975
976 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
977 assert_size(UINT32_MAX, ==, inflater.ctx.hd_table_bufsize_max);
978 assert_size(UINT32_MAX, ==, inflater.settings_hd_table_bufsize_max);
979
980 nva_out_reset(&out, mem);
981 nghttp2_bufs_reset(&bufs);
982
983 nghttp2_hd_inflate_free(&inflater);
984 nghttp2_hd_deflate_free(&deflater);
985
986 /* Check that context update emitted twice */
987 nghttp2_hd_deflate_init2(&deflater, 4096, mem);
988 nghttp2_hd_inflate_init(&inflater, mem);
989
990 assert_int(0, ==, nghttp2_hd_inflate_change_table_size(&inflater, 0));
991 assert_int(0, ==, nghttp2_hd_inflate_change_table_size(&inflater, 3000));
992 assert_int(0, ==, nghttp2_hd_deflate_change_table_size(&deflater, 0));
993 assert_int(0, ==, nghttp2_hd_deflate_change_table_size(&deflater, 3000));
994
995 assert_size(0, ==, deflater.min_hd_table_bufsize_max);
996 assert_size(3000, ==, deflater.ctx.hd_table_bufsize_max);
997
998 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva2, 1);
999 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
1000
1001 assert_int(0, ==, rv);
1002 assert_ptrdiff(3, <, blocklen);
1003 assert_size(3000, ==, deflater.ctx.hd_table_bufsize_max);
1004 assert_size(UINT32_MAX, ==, deflater.min_hd_table_bufsize_max);
1005
1006 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
1007 assert_size(3000, ==, inflater.ctx.hd_table_bufsize_max);
1008 assert_size(3000, ==, inflater.settings_hd_table_bufsize_max);
1009
1010 nva_out_reset(&out, mem);
1011 nghttp2_bufs_reset(&bufs);
1012
1013 nghttp2_hd_inflate_free(&inflater);
1014 nghttp2_hd_deflate_free(&deflater);
1015
1016 nghttp2_bufs_free(&bufs);
1017 }
1018
check_deflate_inflate(nghttp2_hd_deflater * deflater,nghttp2_hd_inflater * inflater,nghttp2_nv * nva,size_t nvlen,nghttp2_mem * mem)1019 static void check_deflate_inflate(nghttp2_hd_deflater *deflater,
1020 nghttp2_hd_inflater *inflater,
1021 nghttp2_nv *nva, size_t nvlen,
1022 nghttp2_mem *mem) {
1023 nghttp2_bufs bufs;
1024 nghttp2_ssize blocklen;
1025 nva_out out;
1026 int rv;
1027
1028 frame_pack_bufs_init(&bufs);
1029
1030 nva_out_init(&out);
1031 rv = nghttp2_hd_deflate_hd_bufs(deflater, &bufs, nva, nvlen);
1032 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
1033
1034 assert_int(0, ==, rv);
1035 assert_ptrdiff(0, <=, blocklen);
1036
1037 assert_ptrdiff(blocklen, ==, inflate_hd(inflater, &out, &bufs, 0, mem));
1038
1039 assert_size(nvlen, ==, out.nvlen);
1040 assert_nv_equal(nva, out.nva, nvlen, mem);
1041
1042 nva_out_reset(&out, mem);
1043 nghttp2_bufs_free(&bufs);
1044 }
1045
test_nghttp2_hd_deflate_inflate(void)1046 void test_nghttp2_hd_deflate_inflate(void) {
1047 nghttp2_hd_deflater deflater;
1048 nghttp2_hd_inflater inflater;
1049 nghttp2_nv nv1[] = {
1050 MAKE_NV(":status", "200 OK"),
1051 MAKE_NV("access-control-allow-origin", "*"),
1052 MAKE_NV("cache-control", "private, max-age=0, must-revalidate"),
1053 MAKE_NV("content-length", "76073"),
1054 MAKE_NV("content-type", "text/html"),
1055 MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1056 MAKE_NV("expires", "Sat, 27 Jul 2013 06:22:12 GMT"),
1057 MAKE_NV("server", "Apache"),
1058 MAKE_NV("vary", "foobar"),
1059 MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1060 MAKE_NV("x-cache", "MISS from alphabravo"),
1061 MAKE_NV("x-cache-action", "MISS"),
1062 MAKE_NV("x-cache-age", "0"),
1063 MAKE_NV("x-cache-lookup", "MISS from alphabravo:3128"),
1064 MAKE_NV("x-lb-nocache", "true"),
1065 };
1066 nghttp2_nv nv2[] = {
1067 MAKE_NV(":status", "304 Not Modified"),
1068 MAKE_NV("age", "0"),
1069 MAKE_NV("cache-control", "max-age=56682045"),
1070 MAKE_NV("content-type", "text/css"),
1071 MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1072 MAKE_NV("expires", "Thu, 14 May 2015 07:22:57 GMT"),
1073 MAKE_NV("last-modified", "Tue, 14 May 2013 07:22:15 GMT"),
1074 MAKE_NV("vary", "Accept-Encoding"),
1075 MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1076 MAKE_NV("x-cache", "HIT from alphabravo"),
1077 MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128")};
1078 nghttp2_nv nv3[] = {
1079 MAKE_NV(":status", "304 Not Modified"),
1080 MAKE_NV("age", "0"),
1081 MAKE_NV("cache-control", "max-age=56682072"),
1082 MAKE_NV("content-type", "text/css"),
1083 MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1084 MAKE_NV("expires", "Thu, 14 May 2015 07:23:24 GMT"),
1085 MAKE_NV("last-modified", "Tue, 14 May 2013 07:22:13 GMT"),
1086 MAKE_NV("vary", "Accept-Encoding"),
1087 MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1088 MAKE_NV("x-cache", "HIT from alphabravo"),
1089 MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
1090 };
1091 nghttp2_nv nv4[] = {
1092 MAKE_NV(":status", "304 Not Modified"),
1093 MAKE_NV("age", "0"),
1094 MAKE_NV("cache-control", "max-age=56682022"),
1095 MAKE_NV("content-type", "text/css"),
1096 MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1097 MAKE_NV("expires", "Thu, 14 May 2015 07:22:34 GMT"),
1098 MAKE_NV("last-modified", "Tue, 14 May 2013 07:22:14 GMT"),
1099 MAKE_NV("vary", "Accept-Encoding"),
1100 MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1101 MAKE_NV("x-cache", "HIT from alphabravo"),
1102 MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
1103 };
1104 nghttp2_nv nv5[] = {
1105 MAKE_NV(":status", "304 Not Modified"),
1106 MAKE_NV("age", "0"),
1107 MAKE_NV("cache-control", "max-age=4461139"),
1108 MAKE_NV("content-type", "application/x-javascript"),
1109 MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1110 MAKE_NV("expires", "Mon, 16 Sep 2013 21:34:31 GMT"),
1111 MAKE_NV("last-modified", "Thu, 05 May 2011 09:15:59 GMT"),
1112 MAKE_NV("vary", "Accept-Encoding"),
1113 MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1114 MAKE_NV("x-cache", "HIT from alphabravo"),
1115 MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
1116 };
1117 nghttp2_nv nv6[] = {
1118 MAKE_NV(":status", "304 Not Modified"),
1119 MAKE_NV("age", "0"),
1120 MAKE_NV("cache-control", "max-age=18645951"),
1121 MAKE_NV("content-type", "application/x-javascript"),
1122 MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1123 MAKE_NV("expires", "Fri, 28 Feb 2014 01:48:03 GMT"),
1124 MAKE_NV("last-modified", "Tue, 12 Jul 2011 16:02:59 GMT"),
1125 MAKE_NV("vary", "Accept-Encoding"),
1126 MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1127 MAKE_NV("x-cache", "HIT from alphabravo"),
1128 MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
1129 };
1130 nghttp2_nv nv7[] = {
1131 MAKE_NV(":status", "304 Not Modified"),
1132 MAKE_NV("age", "0"),
1133 MAKE_NV("cache-control", "max-age=31536000"),
1134 MAKE_NV("content-type", "application/javascript"),
1135 MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1136 MAKE_NV("etag", "\"6807-4dc5b54e0dcc0\""),
1137 MAKE_NV("expires", "Wed, 21 May 2014 08:32:17 GMT"),
1138 MAKE_NV("last-modified", "Fri, 10 May 2013 11:18:51 GMT"),
1139 MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1140 MAKE_NV("x-cache", "HIT from alphabravo"),
1141 MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
1142 };
1143 nghttp2_nv nv8[] = {
1144 MAKE_NV(":status", "304 Not Modified"),
1145 MAKE_NV("age", "0"),
1146 MAKE_NV("cache-control", "max-age=31536000"),
1147 MAKE_NV("content-type", "application/javascript"),
1148 MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1149 MAKE_NV("etag", "\"41c6-4de7d28585b00\""),
1150 MAKE_NV("expires", "Thu, 12 Jun 2014 10:00:58 GMT"),
1151 MAKE_NV("last-modified", "Thu, 06 Jun 2013 14:30:36 GMT"),
1152 MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1153 MAKE_NV("x-cache", "HIT from alphabravo"),
1154 MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
1155 };
1156 nghttp2_nv nv9[] = {
1157 MAKE_NV(":status", "304 Not Modified"),
1158 MAKE_NV("age", "0"),
1159 MAKE_NV("cache-control", "max-age=31536000"),
1160 MAKE_NV("content-type", "application/javascript"),
1161 MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1162 MAKE_NV("etag", "\"19d6e-4dc5b35a541c0\""),
1163 MAKE_NV("expires", "Wed, 21 May 2014 08:32:18 GMT"),
1164 MAKE_NV("last-modified", "Fri, 10 May 2013 11:10:07 GMT"),
1165 MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1166 MAKE_NV("x-cache", "HIT from alphabravo"),
1167 MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
1168 };
1169 nghttp2_nv nv10[] = {
1170 MAKE_NV(":status", "304 Not Modified"),
1171 MAKE_NV("age", "0"),
1172 MAKE_NV("cache-control", "max-age=56682045"),
1173 MAKE_NV("content-type", "text/css"),
1174 MAKE_NV("date", "Sat, 27 Jul 2013 06:22:12 GMT"),
1175 MAKE_NV("expires", "Thu, 14 May 2015 07:22:57 GMT"),
1176 MAKE_NV("last-modified", "Tue, 14 May 2013 07:21:53 GMT"),
1177 MAKE_NV("vary", "Accept-Encoding"),
1178 MAKE_NV("via", "1.1 alphabravo (squid/3.x.x), 1.1 nghttpx"),
1179 MAKE_NV("x-cache", "HIT from alphabravo"),
1180 MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
1181 };
1182 nghttp2_mem *mem;
1183
1184 mem = nghttp2_mem_default();
1185
1186 nghttp2_hd_deflate_init(&deflater, mem);
1187 nghttp2_hd_inflate_init(&inflater, mem);
1188
1189 check_deflate_inflate(&deflater, &inflater, nv1, ARRLEN(nv1), mem);
1190 check_deflate_inflate(&deflater, &inflater, nv2, ARRLEN(nv2), mem);
1191 check_deflate_inflate(&deflater, &inflater, nv3, ARRLEN(nv3), mem);
1192 check_deflate_inflate(&deflater, &inflater, nv4, ARRLEN(nv4), mem);
1193 check_deflate_inflate(&deflater, &inflater, nv5, ARRLEN(nv5), mem);
1194 check_deflate_inflate(&deflater, &inflater, nv6, ARRLEN(nv6), mem);
1195 check_deflate_inflate(&deflater, &inflater, nv7, ARRLEN(nv7), mem);
1196 check_deflate_inflate(&deflater, &inflater, nv8, ARRLEN(nv8), mem);
1197 check_deflate_inflate(&deflater, &inflater, nv9, ARRLEN(nv9), mem);
1198 check_deflate_inflate(&deflater, &inflater, nv10, ARRLEN(nv10), mem);
1199
1200 nghttp2_hd_inflate_free(&inflater);
1201 nghttp2_hd_deflate_free(&deflater);
1202 }
1203
test_nghttp2_hd_no_index(void)1204 void test_nghttp2_hd_no_index(void) {
1205 nghttp2_hd_deflater deflater;
1206 nghttp2_hd_inflater inflater;
1207 nghttp2_bufs bufs;
1208 nghttp2_ssize blocklen;
1209 nghttp2_nv nva[] = {
1210 MAKE_NV(":method", "GET"), MAKE_NV(":method", "POST"),
1211 MAKE_NV(":path", "/foo"), MAKE_NV("version", "HTTP/1.1"),
1212 MAKE_NV(":method", "GET"),
1213 };
1214 size_t i;
1215 nva_out out;
1216 int rv;
1217 nghttp2_mem *mem;
1218
1219 mem = nghttp2_mem_default();
1220
1221 /* 1st :method: GET can be indexable, last one is not */
1222 for (i = 1; i < ARRLEN(nva); ++i) {
1223 nva[i].flags = NGHTTP2_NV_FLAG_NO_INDEX;
1224 }
1225
1226 frame_pack_bufs_init(&bufs);
1227
1228 nva_out_init(&out);
1229
1230 nghttp2_hd_deflate_init(&deflater, mem);
1231 nghttp2_hd_inflate_init(&inflater, mem);
1232
1233 rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, ARRLEN(nva));
1234 blocklen = (nghttp2_ssize)nghttp2_bufs_len(&bufs);
1235
1236 assert_int(0, ==, rv);
1237 assert_ptrdiff(0, <, blocklen);
1238 assert_ptrdiff(blocklen, ==, inflate_hd(&inflater, &out, &bufs, 0, mem));
1239
1240 assert_size(ARRLEN(nva), ==, out.nvlen);
1241 assert_nv_equal(nva, out.nva, ARRLEN(nva), mem);
1242
1243 assert_uint8(NGHTTP2_NV_FLAG_NONE, ==, out.nva[0].flags);
1244 for (i = 1; i < ARRLEN(nva); ++i) {
1245 assert_uint8(NGHTTP2_NV_FLAG_NO_INDEX, ==, out.nva[i].flags);
1246 }
1247
1248 nva_out_reset(&out, mem);
1249
1250 nghttp2_bufs_free(&bufs);
1251 nghttp2_hd_inflate_free(&inflater);
1252 nghttp2_hd_deflate_free(&deflater);
1253 }
1254
test_nghttp2_hd_deflate_bound(void)1255 void test_nghttp2_hd_deflate_bound(void) {
1256 nghttp2_hd_deflater deflater;
1257 nghttp2_nv nva[] = {MAKE_NV(":method", "GET"), MAKE_NV("alpha", "bravo")};
1258 nghttp2_bufs bufs;
1259 size_t bound, bound2;
1260 nghttp2_mem *mem;
1261
1262 mem = nghttp2_mem_default();
1263 frame_pack_bufs_init(&bufs);
1264
1265 nghttp2_hd_deflate_init(&deflater, mem);
1266
1267 bound = nghttp2_hd_deflate_bound(&deflater, nva, ARRLEN(nva));
1268
1269 assert_size(12 + 6 * 2 * 2 + nva[0].namelen + nva[0].valuelen +
1270 nva[1].namelen + nva[1].valuelen,
1271 ==, bound);
1272
1273 nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, ARRLEN(nva));
1274
1275 assert_size((size_t)nghttp2_bufs_len(&bufs), <, bound);
1276
1277 bound2 = nghttp2_hd_deflate_bound(&deflater, nva, ARRLEN(nva));
1278
1279 assert_size(bound, ==, bound2);
1280
1281 nghttp2_bufs_free(&bufs);
1282 nghttp2_hd_deflate_free(&deflater);
1283 }
1284
test_nghttp2_hd_public_api(void)1285 void test_nghttp2_hd_public_api(void) {
1286 nghttp2_hd_deflater *deflater;
1287 nghttp2_hd_inflater *inflater;
1288 nghttp2_nv nva[] = {MAKE_NV("alpha", "bravo"), MAKE_NV("charlie", "delta")};
1289 uint8_t buf[4096];
1290 size_t buflen;
1291 nghttp2_ssize blocklen;
1292 nghttp2_bufs bufs;
1293 nghttp2_mem *mem;
1294
1295 mem = nghttp2_mem_default();
1296
1297 assert_int(0, ==, nghttp2_hd_deflate_new(&deflater, 4096));
1298 assert_int(0, ==, nghttp2_hd_inflate_new(&inflater));
1299
1300 buflen = nghttp2_hd_deflate_bound(deflater, nva, ARRLEN(nva));
1301
1302 blocklen = nghttp2_hd_deflate_hd2(deflater, buf, buflen, nva, ARRLEN(nva));
1303
1304 assert_ptrdiff(0, <, blocklen);
1305
1306 nghttp2_bufs_wrap_init(&bufs, buf, (size_t)blocklen, mem);
1307 bufs.head->buf.last += blocklen;
1308
1309 assert_ptrdiff(blocklen, ==, inflate_hd(inflater, NULL, &bufs, 0, mem));
1310
1311 nghttp2_bufs_wrap_free(&bufs);
1312
1313 nghttp2_hd_inflate_del(inflater);
1314 nghttp2_hd_deflate_del(deflater);
1315
1316 /* See NGHTTP2_ERR_INSUFF_BUFSIZE */
1317 assert_int(0, ==, nghttp2_hd_deflate_new(&deflater, 4096));
1318
1319 blocklen = nghttp2_hd_deflate_hd2(deflater, buf, (size_t)(blocklen - 1), nva,
1320 ARRLEN(nva));
1321
1322 assert_ptrdiff(NGHTTP2_ERR_INSUFF_BUFSIZE, ==, blocklen);
1323
1324 nghttp2_hd_deflate_del(deflater);
1325 }
1326
test_nghttp2_hd_deflate_hd_vec(void)1327 void test_nghttp2_hd_deflate_hd_vec(void) {
1328 nghttp2_hd_deflater *deflater;
1329 nghttp2_hd_inflater *inflater;
1330 nghttp2_nv nva[] = {
1331 MAKE_NV(":method", "PUT"),
1332 MAKE_NV(":scheme", "https"),
1333 MAKE_NV(":authority", "localhost:3000"),
1334 MAKE_NV(":path", "/usr/foo/alpha/bravo"),
1335 MAKE_NV("content-type", "image/png"),
1336 MAKE_NV("content-length", "1000000007"),
1337 };
1338 uint8_t buf[4096];
1339 nghttp2_ssize blocklen;
1340 nghttp2_mem *mem;
1341 nghttp2_vec vec[256];
1342 size_t buflen;
1343 nghttp2_bufs bufs;
1344 nva_out out;
1345 size_t i;
1346
1347 mem = nghttp2_mem_default();
1348
1349 nva_out_init(&out);
1350
1351 nghttp2_hd_deflate_new(&deflater, 4096);
1352 nghttp2_hd_inflate_new(&inflater);
1353
1354 buflen = nghttp2_hd_deflate_bound(deflater, nva, ARRLEN(nva));
1355
1356 vec[0].base = &buf[0];
1357 vec[0].len = buflen / 2;
1358 vec[1].base = &buf[buflen / 2];
1359 vec[1].len = buflen / 2;
1360
1361 blocklen = nghttp2_hd_deflate_hd_vec2(deflater, vec, 2, nva, ARRLEN(nva));
1362
1363 assert_ptrdiff(0, <, blocklen);
1364
1365 nghttp2_bufs_wrap_init(&bufs, buf, (size_t)blocklen, mem);
1366 bufs.head->buf.last += blocklen;
1367
1368 assert_ptrdiff(blocklen, ==, inflate_hd(inflater, &out, &bufs, 0, mem));
1369
1370 assert_size(ARRLEN(nva), ==, out.nvlen);
1371 assert_nv_equal(nva, out.nva, ARRLEN(nva), mem);
1372
1373 nghttp2_bufs_wrap_free(&bufs);
1374
1375 nghttp2_hd_inflate_del(inflater);
1376 nghttp2_hd_deflate_del(deflater);
1377 nva_out_reset(&out, mem);
1378
1379 /* check the case when veclen is 0 */
1380 nghttp2_hd_deflate_new(&deflater, 4096);
1381 nghttp2_hd_inflate_new(&inflater);
1382
1383 blocklen = nghttp2_hd_deflate_hd_vec2(deflater, NULL, 0, nva, ARRLEN(nva));
1384
1385 assert_ptrdiff(NGHTTP2_ERR_INSUFF_BUFSIZE, ==, blocklen);
1386
1387 nghttp2_hd_inflate_del(inflater);
1388 nghttp2_hd_deflate_del(deflater);
1389
1390 /* check the case when chunk length is 0 */
1391 vec[0].base = NULL;
1392 vec[0].len = 0;
1393 vec[1].base = NULL;
1394 vec[1].len = 0;
1395
1396 nghttp2_hd_deflate_new(&deflater, 4096);
1397 nghttp2_hd_inflate_new(&inflater);
1398
1399 blocklen = nghttp2_hd_deflate_hd_vec2(deflater, vec, 2, nva, ARRLEN(nva));
1400
1401 assert_ptrdiff(NGHTTP2_ERR_INSUFF_BUFSIZE, ==, blocklen);
1402
1403 nghttp2_hd_inflate_del(inflater);
1404 nghttp2_hd_deflate_del(deflater);
1405
1406 /* check the case where chunk size differs in each chunk */
1407 nghttp2_hd_deflate_new(&deflater, 4096);
1408 nghttp2_hd_inflate_new(&inflater);
1409
1410 buflen = nghttp2_hd_deflate_bound(deflater, nva, ARRLEN(nva));
1411
1412 vec[0].base = &buf[0];
1413 vec[0].len = buflen / 2;
1414 vec[1].base = &buf[buflen / 2];
1415 vec[1].len = (buflen / 2) + 1;
1416
1417 blocklen = nghttp2_hd_deflate_hd_vec2(deflater, vec, 2, nva, ARRLEN(nva));
1418
1419 assert_ptrdiff(0, <, blocklen);
1420
1421 nghttp2_bufs_wrap_init(&bufs, buf, (size_t)blocklen, mem);
1422 bufs.head->buf.last += blocklen;
1423
1424 assert_ptrdiff(blocklen, ==, inflate_hd(inflater, &out, &bufs, 0, mem));
1425 assert_size(ARRLEN(nva), ==, out.nvlen);
1426 assert_nv_equal(nva, out.nva, ARRLEN(nva), mem);
1427
1428 nghttp2_bufs_wrap_free(&bufs);
1429
1430 nghttp2_hd_inflate_del(inflater);
1431 nghttp2_hd_deflate_del(deflater);
1432 nva_out_reset(&out, mem);
1433
1434 /* check the case where chunk size is 1 */
1435 nghttp2_hd_deflate_new(&deflater, 4096);
1436 nghttp2_hd_inflate_new(&inflater);
1437
1438 buflen = nghttp2_hd_deflate_bound(deflater, nva, ARRLEN(nva));
1439
1440 assert(buflen <= ARRLEN(vec));
1441
1442 for (i = 0; i < buflen; ++i) {
1443 vec[i].base = &buf[i];
1444 vec[i].len = 1;
1445 }
1446
1447 blocklen =
1448 nghttp2_hd_deflate_hd_vec2(deflater, vec, buflen, nva, ARRLEN(nva));
1449
1450 assert_ptrdiff(0, <, blocklen);
1451
1452 nghttp2_bufs_wrap_init(&bufs, buf, (size_t)blocklen, mem);
1453 bufs.head->buf.last += blocklen;
1454
1455 assert_ptrdiff(blocklen, ==, inflate_hd(inflater, &out, &bufs, 0, mem));
1456 assert_size(ARRLEN(nva), ==, out.nvlen);
1457 assert_nv_equal(nva, out.nva, ARRLEN(nva), mem);
1458
1459 nghttp2_bufs_wrap_free(&bufs);
1460
1461 nghttp2_hd_inflate_del(inflater);
1462 nghttp2_hd_deflate_del(deflater);
1463 nva_out_reset(&out, mem);
1464 }
1465
encode_length(uint8_t * buf,uint64_t n,size_t prefix)1466 static size_t encode_length(uint8_t *buf, uint64_t n, size_t prefix) {
1467 size_t k = (size_t)((1 << prefix) - 1);
1468 size_t len = 0;
1469 *buf = (uint8_t)(*buf & ~k);
1470 if (n >= k) {
1471 *buf = (uint8_t)(*buf | k);
1472 ++buf;
1473 n -= k;
1474 ++len;
1475 } else {
1476 *buf = (uint8_t)(*buf | n);
1477 ++buf;
1478 return 1;
1479 }
1480 do {
1481 ++len;
1482 if (n >= 128) {
1483 *buf = (uint8_t)((1 << 7) | (n & 0x7f));
1484 ++buf;
1485 n >>= 7;
1486 } else {
1487 *buf++ = (uint8_t)n;
1488 break;
1489 }
1490 } while (n);
1491 return len;
1492 }
1493
test_nghttp2_hd_decode_length(void)1494 void test_nghttp2_hd_decode_length(void) {
1495 uint32_t out;
1496 size_t shift;
1497 int fin;
1498 uint8_t buf[16];
1499 uint8_t *bufp;
1500 size_t len;
1501 nghttp2_ssize rv;
1502 size_t i;
1503
1504 memset(buf, 0, sizeof(buf));
1505 len = encode_length(buf, UINT32_MAX, 7);
1506
1507 rv = nghttp2_hd_decode_length(&out, &shift, &fin, 0, 0, buf, buf + len, 7);
1508
1509 assert_ptrdiff((nghttp2_ssize)len, ==, rv);
1510 assert_true(fin);
1511 assert_uint32(UINT32_MAX, ==, out);
1512
1513 /* Make sure that we can decode integer if we feed 1 byte at a
1514 time */
1515 out = 0;
1516 shift = 0;
1517 fin = 0;
1518 bufp = buf;
1519
1520 for (i = 0; i < len; ++i, ++bufp) {
1521 rv = nghttp2_hd_decode_length(&out, &shift, &fin, out, shift, bufp,
1522 bufp + 1, 7);
1523
1524 assert_ptrdiff(1, ==, rv);
1525
1526 if (fin) {
1527 break;
1528 }
1529 }
1530
1531 assert_size(len - 1, ==, i);
1532 assert_true(fin);
1533 assert_size(UINT32_MAX, ==, out);
1534
1535 /* Check overflow case */
1536 memset(buf, 0, sizeof(buf));
1537 len = encode_length(buf, 1ll << 32, 7);
1538
1539 rv = nghttp2_hd_decode_length(&out, &shift, &fin, 0, 0, buf, buf + len, 7);
1540
1541 assert_ptrdiff(-1, ==, rv);
1542
1543 /* Check the case that shift goes beyond 32 bits */
1544 buf[0] = 255;
1545 buf[1] = 128;
1546 buf[2] = 128;
1547 buf[3] = 128;
1548 buf[4] = 128;
1549 buf[5] = 128;
1550 buf[6] = 1;
1551
1552 rv = nghttp2_hd_decode_length(&out, &shift, &fin, 0, 0, buf, buf + 7, 8);
1553
1554 assert_ptrdiff(-1, ==, rv);
1555 }
1556
test_nghttp2_hd_huff_encode(void)1557 void test_nghttp2_hd_huff_encode(void) {
1558 int rv;
1559 nghttp2_ssize len;
1560 nghttp2_buf outbuf;
1561 nghttp2_bufs bufs;
1562 nghttp2_hd_huff_decode_context ctx;
1563 const uint8_t t1[] = {22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11,
1564 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
1565 uint8_t b[256];
1566
1567 nghttp2_buf_wrap_init(&outbuf, b, sizeof(b));
1568 frame_pack_bufs_init(&bufs);
1569
1570 rv = nghttp2_hd_huff_encode(&bufs, t1, sizeof(t1));
1571
1572 assert_int(0, ==, rv);
1573
1574 nghttp2_hd_huff_decode_context_init(&ctx);
1575
1576 len = nghttp2_hd_huff_decode(&ctx, &outbuf, bufs.cur->buf.pos,
1577 nghttp2_bufs_len(&bufs), 1);
1578
1579 assert_ptrdiff((nghttp2_ssize)nghttp2_bufs_len(&bufs), ==, len);
1580 assert_size(sizeof(t1), ==, nghttp2_buf_len(&outbuf));
1581
1582 assert_memory_equal(sizeof(t1), t1, outbuf.pos);
1583
1584 nghttp2_bufs_free(&bufs);
1585 }
1586
test_nghttp2_hd_huff_decode(void)1587 void test_nghttp2_hd_huff_decode(void) {
1588 const uint8_t e[] = {0x1f, 0xff, 0xff, 0xff, 0xff, 0xff};
1589 nghttp2_hd_huff_decode_context ctx;
1590 nghttp2_buf outbuf;
1591 uint8_t b[256];
1592 nghttp2_ssize len;
1593
1594 nghttp2_buf_wrap_init(&outbuf, b, sizeof(b));
1595 nghttp2_hd_huff_decode_context_init(&ctx);
1596 len = nghttp2_hd_huff_decode(&ctx, &outbuf, e, 1, 1);
1597
1598 assert_ptrdiff(1, ==, len);
1599 assert_memory_equal(1, "a", outbuf.pos);
1600
1601 /* Premature sequence must elicit decoding error */
1602 nghttp2_buf_wrap_init(&outbuf, b, sizeof(b));
1603 nghttp2_hd_huff_decode_context_init(&ctx);
1604 len = nghttp2_hd_huff_decode(&ctx, &outbuf, e, 2, 1);
1605
1606 assert_ptrdiff(NGHTTP2_ERR_HEADER_COMP, ==, len);
1607
1608 /* Fully decoding EOS is error */
1609 nghttp2_buf_wrap_init(&outbuf, b, sizeof(b));
1610 nghttp2_hd_huff_decode_context_init(&ctx);
1611 len = nghttp2_hd_huff_decode(&ctx, &outbuf, e, 2, 6);
1612
1613 assert_ptrdiff(NGHTTP2_ERR_HEADER_COMP, ==, len);
1614
1615 /* Check failure state */
1616 nghttp2_buf_wrap_init(&outbuf, b, sizeof(b));
1617 nghttp2_hd_huff_decode_context_init(&ctx);
1618 len = nghttp2_hd_huff_decode(&ctx, &outbuf, e, 5, 0);
1619
1620 assert_ptrdiff(5, ==, len);
1621 assert_true(nghttp2_hd_huff_decode_failure_state(&ctx));
1622 }
1623