num-bigint icon indicating copy to clipboard operation
num-bigint copied to clipboard

Unclear panic from `BigUint::to_radix_be` when given radix 1

Open llooFlashooll opened this issue 8 months ago • 3 comments

Hi, when I used afl.rs to test the package, the fuzzer detected unexpected program panics, which I consider to be a bug.

Here is the example code:

extern crate num_bigint;
fn _unwrap_option<T>(_opt: Option<T>) -> T {
    match _opt {
        Some(_t) => _t,
        None => {
            use std::process;
            process::exit(0);
        }
    }
}

fn _to_u32(data:&[u8], index:usize)->u32 {
    let data0 = _to_u16(data, index) as u32;
    let data1 = _to_u16(data, index+2) as u32;
    data0 << 16 | data1
}

fn _to_u8(data:&[u8], index:usize)->u8 {
    data[index]
}

fn _to_slice<T>(data:&[u8], start_index: usize, end_index: usize)->&[T] {
    let data_slice = &data[start_index..end_index];
    let (_, shorts, _) = unsafe {data_slice.align_to::<T>()};
    shorts
}

fn _to_u16(data:&[u8], index:usize)->u16 {
    let data0 = _to_u8(data, index) as u16;
    let data1 = _to_u8(data, index+1) as u16;
    data0 << 8 | data1
}


fn test_function137(_param0: &[u8] ,_param1: u32 ,_param2: u32) {
    let _local0 = num_bigint::BigUint::parse_bytes(_param0 ,_param1);
    let _local1_param0_helper1 = _unwrap_option(_local0);
    num_bigint::BigUint::to_radix_be(&(_local1_param0_helper1) ,_param2);
}

fn _read_data()-> Vec<u8> {
    use std::env;
    use std::process::exit;
    let args:Vec<String> = env::args().collect();
    if args.len() < 2 {
        println!("No crash filename provided");
        exit(-1);
    }
    use std::path::PathBuf;
    let crash_file_name = &args[1];
    let crash_path = PathBuf::from(crash_file_name);
    if !crash_path.is_file() {
        println!("Not a valid crash file");
        exit(-1);
    }
    use std::fs;
    let data =  fs::read(crash_path).unwrap();
    data
}

fn main() {
    let _content = _read_data();
    let data = &_content;
    println!("data = {:?}", data);
    println!("data len = {:?}", data.len());
    //actual body emit
    if data.len() < 9 {return;}
    let dynamic_length = (data.len() - 8) / 1;
    let _param0 = _to_slice::<u8>(data, 8 + 0 * dynamic_length, data.len());
    let _param1 = _to_u32(data, 0);
    let _param2 = _to_u32(data, 4);
    test_function137(_param0 ,_param1 ,_param2);

}

The crash file is: crash_file.zip

We can reproduce the crash by running the program with the crash file as the argument.

Here is the corresponding stack trace and panic message:

../num-bigint/fuzz_target/num_bigint_wubfs_generic_fuzz/multipleTargets/target/debug/replay_num_bigint137 ../num-bigint/fuzz_target/num_bigint_wubfs_generic_fuzz/multipleTargets/out/test_num_bigint137/default/crashes/id:000012,sig:06,src:000069,time:102455,execs:42851,op:havoc,rep:1
data = [0, 0, 0, 32, 0, 0, 0, 1, 48, 49]
data len = 10

thread 'main' panicked at ../num-bigint/src/biguint/convert.rs:756:12:
attempt to calculate the remainder with a divisor of zero
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

The rustc version is 1.76.0, the afl.rs version is 0.15.9, the package version is the latest.

Please check if these are real bugs that need to be fixed. Thanks!

llooFlashooll avatar Apr 28 '25 08:04 llooFlashooll

num_bigint::BigUint::to_radix_be(&(_local1_param0_helper1) ,_param2);

It appears this is passing radix 1 (in _param2), which is an invalid input for that function: "radix must be in the range 2...256." Since this function does not have an Option/Result return value for errors, a panic is expected. Then this particular case got to the divide-by-zero here:

https://github.com/rust-num/num-bigint/blob/a25836ec6c341d1aa40c97335842f330b6a62911/src/biguint/convert.rs#L755-L756

I think the only action for us is to directly document that out-of-range values will panic, and we should probably also add a more explicit assertion for the range.

cuviper avatar Apr 28 '25 16:04 cuviper

Thank you very much for your timely reply! Do you think it is an important issue that needs to be fixed?

llooFlashooll avatar Apr 29 '25 04:04 llooFlashooll

It's a bad input, so a panic is expected. There's no fix possible, only improved communication about the issue.

cuviper avatar Apr 29 '25 15:04 cuviper