ChainSafe / ChainSafe/gossamer
Fuzzing result for MultihashFromBytes target
- Dominant language
- Go
- Stars
- 454
- Forks
- 144
- PR merge metrics
- No merged PRs in 30d
Description
# Target
### ```Substrate```
```multihash = { version = "0.16" }```
```rust
#[cfg_attr(feature = "serde-codec", derive(serde::Deserialize))]
#[cfg_attr(feature = "serde-codec", derive(serde::Serialize))]
#[derive(Clone, Copy, Debug, Eq, Ord, PartialOrd)]
pub struct Multihash {
/// The code of the Multihash.
code: u64,
/// The actual size of the digest in bytes (not the allocated size).
size: u8,
/// The digest.
#[cfg_attr(feature = "serde-codec", serde(with = "BigArray"))]
digest: [u8; S],
}
/// Parses a multihash from a bytes.
///
/// You need to make sure the passed in bytes have the correct length. The digest length
/// needs to match the `size` value of the multihash.
pub fn from_bytes(mut bytes: &[u8]) -> Result
where
Self: Sized,
{
let result = Self::read(&mut bytes)?;
// There were more bytes supplied than read
if !bytes.is_empty() {
return Err(Error::InvalidSize(bytes.len().try_into().expect(
"Currently the maximum size is 255, therefore always fits into usize",
)));
}
Ok(result)
}
```
### ```Smoldot```
```rust
pub struct MultihashRef<'a>(u32, &'a [u8]);
/// Checks whether `input` is a valid multihash.
pub fn from_bytes(input: &'a [u8]) -> Result {
match nom::combinator::all_consuming(multihash::>)(input) {
Ok((_rest, multihash)) => {
debug_assert!(_rest.is_empty());
Ok(multihash)
}
Err(_) => Err(FromBytesError::DecodeError),
}
}
```
### ```Gossamer```
```"github.com/multiformats/go-multihash"```
```go
// MHFromBytes reads a multihash from the given byte buffer, returning the
// number of bytes read as well as the multihash
func MHFromBytes(buf []byte) (int, Multihash, error) {
nr, _, _, err := readMultihashFromBuf(buf)
if err != nil {
return 0, nil, err
}
return nr, Multihash(buf[:nr]), nil
}
```
# ```MultihashFromBytes``` Reproducing Scripts
### ```Substrate```
```rust
pub fn substrate_multihash_from_bytes(file_name: &String) {
println!("[+] Substrate Result:");
let buf = read_bytes(file_name).unwrap();
let ret = multihash::Multihash::from_bytes(&buf);
if let Err(_) = ret {
println!("[-] Multihash from_bytes result: {:?}", ret);
} else {
println!("[+] Multihash from_bytes result: {:?}", ret);
}
}
```
### ```Smoldot```
```rust
pub fn smoldot_multihash_from_bytes(file_name: &String) {
println!("[+] Smoldot Result:");
let buf = read_bytes(file_name).unwrap();
let ret = smoldot::libp2p::multihash::MultihashRef::from_bytes(&buf);
if let Err(_) = ret {
println!("[-] Multihash from_bytes result: {:?}", ret);
} else {
println!("[+] Multihash from_bytes result: {:?}", ret);
}
}
```
### ```Gossamer```
```go
func glib_multihash_from_bytes(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
_, ret, err := mh.MHFromBytes(data)
if err != nil {
fmt.Println("[-] Multihash mh.MHFromBytes result:", err)
} else {
fmt.Println("[+] Multihash mh.MHFromBytes result:", ret)
}
}
```
# Crash
The differential fuzzer catches a crash. The ```Substrate``` and ```Smoldot``` targets give an error message but the ```Gossamer``` target executes the given data successfully.
### ```Reproducer``` crash report
```
./reproducer run all MultihashFromBytes /crash-b74eca758e6bb81efaacac6db1ad86cd2533951e
[+] Smoldot Result:
[-] Multihash from_bytes result: Err(DecodeError)
[+] Substrate Result:
[-] Multihash from_bytes result: Err(InvalidSize(6))
[+] Gossamer Result:
[+] Multihash mh.MHFromBytes result: 0000
```
### Artifacts
[multihashfrombytes_crash.zip](https://github.com/ChainSafe/gossamer/files/10724004/multihashfrombytes_crash.zip)
Contributor guide
Assessment
This issue has not been assessed yet.