bincode-org / bincode

A binary encoder / decoder implementation in Rust.
MIT License
2.63k stars 265 forks source link

Panic/memory allocation of x bytes failed with 1.3.3 version of bincode #676

Closed qarmin closed 10 months ago

qarmin commented 10 months ago

Project - ttttt.zip Code

use std::collections::BTreeSet;
use std::fs::File;

use serde_derive::Deserialize;
use serde_derive::Serialize;

#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct DifferentHeavyStruct {
    pub st: String,
    pub path: String,
    pub another_problem: String,
    pub ss: bool,
    pub sss: bool,
    pub ssss: bool,
    pub sssss: u32,
    pub ssssss: i32,
    pub sssssss: u64,
    pub ssssssss: i64,
    pub cc: Vec<u8>,
    pub cc2: Vec<u8>,
    pub cc5: Vec<u8>,
    pub cc6: Vec<u8>,
}

#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct HeavyStruct {
    pub st: String,
    pub path: String,
    pub another_problem: String,
    pub ss: bool,
    pub sss: bool,
    pub ssss: bool,
    pub sssss: u32,
    pub ssssss: i32,
    pub sssssss: u64,
    pub ssssssss: i64,
    pub cc: Vec<u8>,
    pub cc2: Vec<u8>,
    pub cc3: Vec<u8>,
}

fn main() {
    let mut vec = Vec::new();

    for i in 0..(rand::random::<u32>() % 10 + 101) {
        for _ in 0..(rand::random::<u32>() % 1000 + 1) {
            let mut ss = Vec::new();
            for _ in 0..(rand::random::<u32>() % 20 + 1) {
                ss.push(rand::random());
            }
            vec.push(HeavyStruct {
                st: String::from("Hello"),
                path: "".to_string(),
                another_problem: "".to_string(),
                ss: rand::random(),
                sss: rand::random(),
                ssss: rand::random(),
                sssss: rand::random(),
                ssssss: rand::random(),
                sssssss: rand::random(),
                ssssssss: rand::random(),
                cc: ss.clone(),
                cc2: ss.clone(),
                cc3: ss,
            });
        }
        {
            let file_handler = File::create("test.bin").unwrap();
            bincode::serialize_into::<File, Vec<HeavyStruct>>(file_handler, &vec).unwrap();
        }
        {
            let file_handler = File::open("test.bin").unwrap();
            let r = bincode::deserialize_from::<File, BTreeSet<DifferentHeavyStruct>>(file_handler);
            if r.is_ok() {
                println!("OK");
            } else {
                println!("{r:?}");
            }
        }
    }

    println!("Hello, world!");
}

crashes with random messages

memory allocation of 3307642593290027009 bytes failed
thread 'main' panicked at library/alloc/src/raw_vec.rs:534:5:
capacity overflow
stack backtrace:
   0: rust_begin_unwind
             at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/std/src/panicking.rs:595:5
   1: core::panicking::panic_fmt
             at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/core/src/panicking.rs:67:14
   2: alloc::raw_vec::capacity_overflow
             at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/alloc/src/raw_vec.rs:534:5
   3: alloc::raw_vec::handle_reserve
             at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/alloc/src/raw_vec.rs:505:34
   4: alloc::raw_vec::RawVec<T,A>::reserve::do_reserve_and_handle
             at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/alloc/src/raw_vec.rs:289:13
   5: alloc::raw_vec::RawVec<T,A>::reserve
             at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/alloc/src/raw_vec.rs:293:13
   6: alloc::vec::Vec<T,A>::reserve
             at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/alloc/src/vec/mod.rs:909:18
   7: alloc::vec::Vec<T,A>::extend_with
             at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/alloc/src/vec/mod.rs:2477:9
   8: alloc::vec::Vec<T,A>::resize
             at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/alloc/src/vec/mod.rs:2359:13
   9: bincode::de::read::IoReader<R>::fill_buffer
             at /home/rafal/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bincode-1.3.3/src/de/read.rs:144:9
  10: <bincode::de::read::IoReader<R> as bincode::de::read::BincodeRead>::get_byte_buffer
             at /home/rafal/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bincode-1.3.3/src/de/read.rs:171:9
  11: bincode::de::Deserializer<R,O>::read_vec
             at /home/rafal/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bincode-1.3.3/src/de/mod.rs:96:9
  12: bincode::de::Deserializer<R,O>::read_string
             at /home/rafal/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bincode-1.3.3/src/de/mod.rs:100:19
  13: <&mut bincode::de::Deserializer<R,O> as serde::de::Deserializer>::deserialize_string
             at /home/rafal/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bincode-1.3.3/src/de/mod.rs:244:30
  14: serde::de::impls::<impl serde::de::Deserialize for alloc::string::String>::deserialize
             at /home/rafal/.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde-1.0.190/src/de/impls.rs:604:9
  15: <core::marker::PhantomData<T> as serde::de::DeserializeSeed>::deserialize
             at /home/rafal/.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde-1.0.190/src/de/mod.rs:794:9
  16: <<&mut bincode::de::Deserializer<R,O> as serde::de::Deserializer>::deserialize_tuple::Access<R,O> as serde::de::SeqAccess>::next_element_seed
             at /home/rafal/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bincode-1.3.3/src/de/mod.rs:314:25
  17: serde::de::SeqAccess::next_element
             at /home/rafal/.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde-1.0.190/src/de/mod.rs:1726:9
  18: <ttttt::_::<impl serde::de::Deserialize for ttttt::DifferentHeavyStruct>::deserialize::__Visitor as serde::de::Visitor>::visit_seq
             at ./src/main.rs:7:21
  19: <&mut bincode::de::Deserializer<R,O> as serde::de::Deserializer>::deserialize_tuple
             at /home/rafal/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bincode-1.3.3/src/de/mod.rs:326:9
  20: <&mut bincode::de::Deserializer<R,O> as serde::de::Deserializer>::deserialize_struct
             at /home/rafal/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bincode-1.3.3/src/de/mod.rs:411:9
  21: ttttt::_::<impl serde::de::Deserialize for ttttt::DifferentHeavyStruct>::deserialize
             at ./src/main.rs:7:21
  22: <core::marker::PhantomData<T> as serde::de::DeserializeSeed>::deserialize
             at /home/rafal/.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde-1.0.190/src/de/mod.rs:794:9
  23: <<&mut bincode::de::Deserializer<R,O> as serde::de::Deserializer>::deserialize_tuple::Access<R,O> as serde::de::SeqAccess>::next_element_seed
             at /home/rafal/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bincode-1.3.3/src/de/mod.rs:314:25
  24: serde::de::SeqAccess::next_element
             at /home/rafal/.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde-1.0.190/src/de/mod.rs:1726:9
  25: <serde::de::impls::<impl serde::de::Deserialize for alloc::collections::btree::set::BTreeSet<T>>::deserialize::SeqVisitor<T> as serde::de::Visitor>::visit_seq
             at /home/rafal/.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde-1.0.190/src/de/impls.rs:918:54
  26: <&mut bincode::de::Deserializer<R,O> as serde::de::Deserializer>::deserialize_tuple
             at /home/rafal/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bincode-1.3.3/src/de/mod.rs:326:9
  27: <&mut bincode::de::Deserializer<R,O> as serde::de::Deserializer>::deserialize_seq
             at /home/rafal/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bincode-1.3.3/src/de/mod.rs:350:9
  28: serde::de::impls::<impl serde::de::Deserialize for alloc::collections::btree::set::BTreeSet<T>>::deserialize
             at /home/rafal/.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde-1.0.190/src/de/impls.rs:927:17
  29: <core::marker::PhantomData<T> as serde::de::DeserializeSeed>::deserialize
             at /home/rafal/.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde-1.0.190/src/de/mod.rs:794:9
  30: bincode::internal::deserialize_from_custom_seed
             at /home/rafal/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bincode-1.3.3/src/internal.rs:88:5
  31: bincode::internal::deserialize_from_seed
             at /home/rafal/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bincode-1.3.3/src/internal.rs:65:5
  32: bincode::internal::deserialize_from
             at /home/rafal/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bincode-1.3.3/src/internal.rs:55:5
  33: bincode::config::Options::deserialize_from
             at /home/rafal/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bincode-1.3.3/src/config/mod.rs:229:9
  34: bincode::deserialize_from
             at /home/rafal/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bincode-1.3.3/src/lib.rs:129:5
  35: ttttt::main
             at ./src/main.rs:74:21
  36: core::ops::function::FnOnce::call_once
             at /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
VictorKoenders commented 10 months ago

You serialize Vec<HeavyStruct> but you deserialize BTreeSet<DifferentHeavyStruct>. These two structs are different, bincode does not support this

qarmin commented 10 months ago

I know that - I wanted to find minimal code that cause panic/crash.

Crashing entire app is not right solution when trying to deserialize untrusted file, so here should be returned Err() like in similar invalid situations

ZoeyR commented 10 months ago

You need to configure bincode to limit its possible allocation. Refer to this documentation on how to do that https://docs.rs/bincode/latest/bincode/config/trait.Options.html#method.with_limit