Skip to content

Fuzzing result for DecodeBabeNextEpoch target #2

@armaganyildirak

Description

@armaganyildirak

Target

Substrate

#[derive(Decode, Encode, PartialEq, Eq, Clone, RuntimeDebug)]
pub struct NextEpochDescriptor {
	/// The authorities.
	pub authorities: Vec<(AuthorityId, BabeAuthorityWeight)>,

	/// The value of randomness to use for the slot-assignment.
	pub randomness: Randomness,
}

Smoldot

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BabeNextEpochRef<'a> {
    /// The authorities.
    pub authorities: BabeAuthoritiesIter<'a>,

    /// The value of randomness to use for the slot-assignment.
    pub randomness: &'a [u8; 32],
}

Gossamer

type NextEpochData struct {
	Authorities []AuthorityRaw
	Randomness  [RandomnessLength]byte
}

DecodeBabeNextEpoch Reproducing Scripts

Substrate

pub fn substrate_decode_babenextepoch(file_name: &String) {
    println!("[+] Substrate Result:");
    let buf = read_bytes(file_name).unwrap();
    let mut data: &[u8] = buf.as_ref();
    let ret = NextEpochDescriptor::decode(&mut data);
    if let Err(_) = ret {
        println!("[-] BabeNextEpoch decode result: {:?}", ret);
    } else {
        println!("[+] BabeNexetEpoch decode result: {:?}", ret);
    }
}

Smoldot

pub fn smoldot_decode_babenextepoch(file_name: &String) {
    println!("[+] Smoldot Result:");
    let buf = read_bytes(file_name).unwrap();
    let ret = smoldot::header::BabeNextEpochRef::from_slice(&buf);
    if let Err(_) = ret {
        println!("[-] BabeNextEpoch from_bytes result: {:?}", ret);
    } else {
        println!("[+] BabeNextEpoch from_bytes result: {:?}", ret);
    }
}

Gossamer

func glib_decode_babenextepoch(data_ptr unsafe.Pointer, data_size int) {
	fmt.Println("[+] Gossamer Result:")
	var data []byte
	sh := (*reflect.SliceHeader)(unsafe.Pointer(&data))
	sh.Data = uintptr(data_ptr)
	sh.Len = data_size
	sh.Cap = data_size
	dec := types.NextEpochData{}
	err := scale.Unmarshal(data, &dec)
	if err != nil {
		fmt.Println("[-] BabeNextEpoch scale.Unmarshal result:", err)
	} else {
		fmt.Println("[+] BabeNextEpoch scale.Unmarshal result:", dec)
	}
}

Reproducing Crash

The DecodeBabeNextEpoch target is trying to decode the given structure. When the fuzzers send the same inputs to the clients, the Smoldot client gives an attempting overflow panic message because authorities_len is calculated as big number and it multiplies with 40 in src/header/babe.rs:150, the Substrate client gives an error message and the Gossamer client gives an error message. The reproducing scripts were added to reproducer part.

Substrate

./reproducer run substrate decodebabenextepoch  <path-to-crashfile>/crash-3f735c6da5488480bfbf040bfbc14d3dda9f2a14

[+] Substrate Result:
[-] BabeNextEpoch decode result: Err(Error { cause: Some(Error { cause: None, desc: "out of range decoding Compact<u32>" }), desc: "Could not decode `NextEpochDescriptor::authorities`" })

Smoldot

./reproducer run smoldot decodebabenextepoch <path-to-crashfile>/crashes/crash-3f735c6da5488480bfbf040bfbc14d3dda9f2a14

[+] Smoldot Result:
thread 'main' panicked at 'attempt to multiply with overflow', polkafuzz/clients/smoldot/src/header/babe.rs:150:27
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Gossamer

./reproducer run gossamer decodebabenextepoch <path-to-crashfile>/crash-3f735c6da5488480bfbf040bfbc14d3dda9f2a14

[+] Gossamer Result:
[-] BabeNextEpoch scale.Unmarshal result: EOF, field: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0], field: []

Artifacts

decode_babenextepoch_crashes.zip

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions