• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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