My own corner of monopam
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

idc: reject stream dimensions that disagree with the caller's

[decompress] ignored its [~width]/[~height] arguments and trusted
whatever the bitstream header declared. A fuzz input of 5 bytes
decoded into a 5757x51873 stream, which drove [array_2d] to
allocate ~300M entries and parked [inverse_dwt_2d] in a multi-minute
loop.

Thread the expected dimensions through [decode_coefficients] and
fail with [invalid_arg] before allocating when they don't match the
header. The mli documents [~width]/[~height] as the expected output
size, so this only rejects malformed streams.

Fixes the fuzz-test failure surfaced by
[test_decompress_crash_safety] on input "\022}\202\161_".

+13 -3
+13 -3
ocaml-idc/lib/idc.ml
··· 537 537 done; 538 538 Bitstream.contents bw 539 539 540 - let decode_coefficients data = 540 + let decode_coefficients ~expected_width ~expected_height data = 541 541 let br = Bitstream.of_bytes data in 542 542 let width = Bitstream.read_bits br 16 in 543 543 let height = Bitstream.read_bits br 16 in 544 + (* Trust the caller's dimensions: attacker-supplied [data] can declare 545 + a 65535x65535 stream in its header, which would otherwise drive 546 + [array_2d] to allocate billions of cells and park 547 + [inverse_dwt_2d] in a multi-minute loop. *) 548 + if width <> expected_width || height <> expected_height then 549 + invalid_arg 550 + (Fmt.str "Idc.decompress: stream declares %dx%d, expected %dx%d" width 551 + height expected_width expected_height); 544 552 let levels = Bitstream.read_bits br 8 in 545 553 let wavelet = wavelet_of_id (Bitstream.read_bits br 8) in 546 554 let max_mag = Bitstream.read_bits br 16 in ··· 584 592 let arr = quantize_2d farr height width in 585 593 encode_coefficients ~wavelet ~width ~height arr 586 594 587 - let decompress ~width:_ ~height:_ data = 588 - let w, h, levels, wavelet, arr = decode_coefficients data in 595 + let decompress ~width ~height data = 596 + let w, h, levels, wavelet, arr = 597 + decode_coefficients ~expected_width:width ~expected_height:height data 598 + in 589 599 match wavelet with 590 600 | `Int_5_3 -> 591 601 inverse_dwt_2d arr w h levels;