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