@@ -305,86 +305,97 @@ static inline bool consume(struct bit_reader *reader, int count)
305
305
return reader -> total_bitcount > 0 ;
306
306
}
307
307
308
- static inline size_t output_size (size_t input_size )
308
+ DEFINE_RING_BUFFER_TYPE (uint8_ring_buffer , uint8_t , 64 )
309
+
310
+ struct lwan_h2_huffman_decoder {
311
+ struct bit_reader bit_reader ;
312
+ struct uint8_ring_buffer buffer ;
313
+ };
314
+
315
+ void lwan_h2_huffman_init (struct lwan_h2_huffman_decoder * huff ,
316
+ const uint8_t * input ,
317
+ size_t input_len )
309
318
{
310
- /* Smallest input is 5 bits which produces 8 bits. Scaling that to 8 bits,
311
- * we get 12.8 bits of output per 8 bits of input. */
312
- return (input_size * 128 ) / 10 ;
319
+ huff -> bit_reader = (struct bit_reader ){
320
+ .bitptr = input ,
321
+ .total_bitcount = (int64_t )input_len * 8 ,
322
+ };
323
+ uint8_ring_buffer_init (& huff -> buffer );
313
324
}
314
325
315
- uint8_t * lwan_h2_huffman_decode_for_fuzzing (const uint8_t * input ,
316
- size_t input_len )
326
+ ssize_t lwan_h2_huffman_next (struct lwan_h2_huffman_decoder * huff )
317
327
{
318
- uint8_t * output = malloc (output_size (input_len ));
319
- uint8_t * ret = output ;
320
- struct bit_reader bit_reader = {.bitptr = input ,
321
- .total_bitcount = (int64_t )input_len * 8 };
328
+ struct bit_reader * reader = & huff -> bit_reader ;
329
+ struct uint8_ring_buffer * buffer = & huff -> buffer ;
322
330
323
- while (bit_reader .total_bitcount > 7 ) {
324
- uint8_t peeked_byte = peek_byte (& bit_reader );
331
+ while (reader -> total_bitcount > 7 ) {
332
+ if (uint8_ring_buffer_full (buffer ))
333
+ goto done ;
334
+
335
+ uint8_t peeked_byte = peek_byte (reader );
325
336
if (LIKELY (level0 [peeked_byte ].num_bits )) {
326
- * output ++ = level0 [peeked_byte ].symbol ;
327
- consume (& bit_reader , level0 [peeked_byte ].num_bits );
337
+ uint8_ring_buffer_put_copy ( buffer , level0 [peeked_byte ].symbol ) ;
338
+ consume (reader , level0 [peeked_byte ].num_bits );
328
339
assert (bit_reader .total_bitcount >= 0 );
329
340
continue ;
330
341
}
331
342
332
- if (!consume (& bit_reader , 8 ))
333
- goto fail ;
343
+ if (!consume (reader , 8 ))
344
+ return -1 ;
334
345
335
346
const struct h2_huffman_code * level1 = next_level0 (peeked_byte );
336
- peeked_byte = peek_byte (& bit_reader );
347
+ peeked_byte = peek_byte (reader );
337
348
if (level1 [peeked_byte ].num_bits ) {
338
- * output ++ = level1 [peeked_byte ].symbol ;
339
- if (!consume (& bit_reader , level1 [peeked_byte ].num_bits ))
340
- goto fail ;
349
+ uint8_ring_buffer_put_copy ( buffer , level1 [peeked_byte ].symbol ) ;
350
+ if (!consume (reader , level1 [peeked_byte ].num_bits ))
351
+ return -1 ;
341
352
continue ;
342
353
}
343
354
344
- if (!consume (& bit_reader , 8 ))
345
- goto fail ;
355
+ if (!consume (reader , 8 ))
356
+ return -1 ;
346
357
347
358
const struct h2_huffman_code * level2 = next_level1 (peeked_byte );
348
- peeked_byte = peek_byte (& bit_reader );
359
+ peeked_byte = peek_byte (reader );
349
360
if (level2 [peeked_byte ].num_bits ) {
350
- * output ++ = level2 [peeked_byte ].symbol ;
351
- if (!consume (& bit_reader , level2 [peeked_byte ].num_bits ))
352
- goto fail ;
361
+ uint8_ring_buffer_put_copy ( buffer , level2 [peeked_byte ].symbol ) ;
362
+ if (!consume (reader , level2 [peeked_byte ].num_bits ))
363
+ return -1 ;
353
364
continue ;
354
365
}
355
366
356
- if (!consume (& bit_reader , 8 ))
367
+ if (!consume (reader , 8 ))
357
368
goto fail ;
358
369
359
370
const struct h2_huffman_code * level3 = next_level2 (peeked_byte );
360
371
if (LIKELY (level3 )) {
361
- peeked_byte = peek_byte (& bit_reader );
372
+ peeked_byte = peek_byte (reader );
362
373
if (level3 [peeked_byte ].num_bits < 0 ) {
363
374
/* EOS found */
364
- return ret ;
375
+ goto done ;
365
376
}
366
377
if (LIKELY (level3 [peeked_byte ].num_bits )) {
367
- * output ++ = level3 [peeked_byte ].symbol ;
368
- if (!consume (& bit_reader , level3 [peeked_byte ].num_bits ))
369
- goto fail ;
378
+ uint8_ring_buffer_put_copy ( buffer , level3 [peeked_byte ].symbol ) ;
379
+ if (!consume (reader , level3 [peeked_byte ].num_bits ))
380
+ return -1 ;
370
381
continue ;
371
382
}
372
383
}
373
384
374
- goto fail ;
385
+ return -1 ;
375
386
}
376
387
377
388
/* FIXME: ensure we're not promoting types unnecessarily here */
378
- if (bit_reader . total_bitcount ) {
379
- const uint8_t peeked_byte = peek_byte (& bit_reader );
389
+ if (reader -> total_bitcount ) {
390
+ const uint8_t peeked_byte = peek_byte (reader );
380
391
const uint8_t eos_prefix = ((1 << bit_reader .total_bitcount ) - 1 )
381
392
<< (8 - bit_reader .total_bitcount );
382
393
383
394
if ((peeked_byte & eos_prefix ) == eos_prefix )
384
395
goto done ;
385
396
386
- if (level0 [peeked_byte ].num_bits == (int8_t )bit_reader . total_bitcount ) {
387
- * output = level0 [peeked_byte ].symbol ;
397
+ if (level0 [peeked_byte ].num_bits == (int8_t )reader -> total_bitcount ) {
398
+ uint8_ring_buffer_put_copy ( buffer , level0 [peeked_byte ].symbol ) ;
388
399
goto done ;
389
400
}
390
401
@@ -393,15 +404,28 @@ uint8_t *lwan_h2_huffman_decode_for_fuzzing(const uint8_t *input,
393
404
* - Incomplete sequence
394
405
* - Has overlong padding
395
406
*/
396
- goto fail ;
407
+ return -1 ;
397
408
}
398
409
399
410
done :
400
- return ret ;
401
-
402
- fail :
403
- free (ret );
404
- return NULL ;
411
+ return (ssize_t )uint8_ring_buffer_size (buffer );
405
412
}
406
413
414
+ bool lwan_h2_huffman_decode_for_fuzzing (const uint8_t * input , size_t input_len )
415
+ {
416
+ struct lwan_h2_huffman_decoder decoder ;
417
+
418
+ lwan_h2_huffman_init (& decoder , input , input_len );
419
+
420
+ while (true) {
421
+ ssize_t n_decoded = lwan_h2_huffman_next (& decoder );
422
+
423
+ if (UNLIKELY (n_decoded < 0 ))
424
+ return false;
425
+ if (n_decoded < 64 )
426
+ return true;
427
+
428
+ uint8_ring_buffer_init (& decoder -> buffer );
429
+ }
430
+ }
407
431
#endif
0 commit comments