The Deserialize implementation builds the target map with Map::with_capacity_none(map.len()) and then inserts every entry by its original key. For a sparse map the highest key is larger than the number of entries, so the insert crosses the boundary and panics.
Reproduction
let mut before: Map<u8> = Map::with_capacity_none(32);
before.insert(0, 1);
before.insert(31, 2);
let bytes: Vec<u8> = bincode::serialize(&before).unwrap();
let after: Map<u8> = bincode::deserialize(&bytes).unwrap();
Result: The key 31 is over the boundary 2.
Two more gaps in the same code path
usize::MAX is reserved internally as the NodeId::UNDEF sentinel, but the visitor accepts it as a key.
max_key + 1 is used as the capacity without checking that Layout::array::<Node<V>> can represent it, so a crafted payload turns into an allocation failure instead of a deserialization error.
Expected
- Capacity is
max_key + 1, so every entry is inserted at its original key.
- A
usize::MAX key is rejected with a serde error.
- A capacity that exceeds the addressable range is rejected with a serde error.
Plan
@yegor256, please take a look.
The
Deserializeimplementation builds the target map withMap::with_capacity_none(map.len())and then inserts every entry by its original key. For a sparse map the highest key is larger than the number of entries, so the insert crosses the boundary and panics.Reproduction
Result:
The key 31 is over the boundary 2.Two more gaps in the same code path
usize::MAXis reserved internally as theNodeId::UNDEFsentinel, but the visitor accepts it as a key.max_key + 1is used as the capacity without checking thatLayout::array::<Node<V>>can represent it, so a crafted payload turns into an allocation failure instead of a deserialization error.Expected
max_key + 1, so every entry is inserted at its original key.usize::MAXkey is rejected with a serde error.Plan
max_key + 1.serde::de::Error::custom.@yegor256, please take a look.