dholroyd / h264-reader

Rust reader for H264 bitsream syntax
Apache License 2.0
72 stars 25 forks source link

Panic from 'attempt to add with overflow' in qs_y calculation #58

Open wrv opened 1 year ago

wrv commented 1 year ago

https://github.com/dholroyd/h264-reader/blob/8cae2315eee5796b297a412d388c7cf797b386da/src/nal/slice/mod.rs#L602C74-L602C74

A missing bounds check in pps.pic_init_qs_minus26 can cause an overflow when calculating qs_y.

Here is an input with pps.pic_init_qs_minus26 set to -285 and slice_qs_delta set to -2147483645:

vec![0x00, 0x00, 0x00, 0x01, 0x67, 0x64, 0x00, 0x0B, 0xAC,
     0xD9, 0x42, 0x4D, 0xF8, 0x84, 0x00, 0x00, 0x00, 0x01,
     0x68, 0xEB, 0xE8, 0x02, 0x3B, 0x2C, 0x8B, 0x00, 0x00,
     0x01, 0x65, 0x96, 0x10, 0x00, 0x64, 0x00, 0x00, 0x03,
     0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xD2, 0x88,
     0x4D, 0x64, 0x00, 0x23, 0xA0, 0x2B, 0xF7, 0xE3, 0x9A,
     0x89, 0xE0, 0x00, 0x00, 0x00, 0x01, 0x41, 0x9A, 0x21,
     0x6C, 0x41, 0x97, 0x2E, 0xB0];

The syntax element pps.pic_init_qs_minus26 should be in the range [-26, 25].

Found with H26Forge.

wrv commented 1 year ago

To produce the PoC video with H26Forge, you can use the following transform:

##
# Overflows a qs_y calculation, triggering potential issues while decoding
#
# Save this file as `overflowing_qs_y.py`
# Run with `./h26forge modify -i input_vids/SPS_PPS_I_P.264 -o overflowing_qs_y.264 -t overflowing_qs_y.py`
#
def overflow_qs_y(ds):
    ds["ppses"][0]["pic_init_qs_minus26"] = -285
    # SI slice
    ds["slices"][0]["sh"]["slice_type"] = 4
    ds["slices"][0]["sh"]["slice_qs_delta"] = -2147483645
    return ds

def modify_video(ds):
    return overflow_qs_y(ds)