Stop untrusted preallocation during JoinSplit deserialization
Zebra believes the untrusted `JoinSplit` list size field when deserializing `JoinSplit`s, and preallocates a `Vec` based on that size. This is trivial a memory exhaustion attack. Instead, use the current auto-growing implementation, which is limited by the size of the message data.
This commit is contained in:
parent
f19f0d0949
commit
db2f920d96
|
@ -44,24 +44,22 @@ impl<P: ZkSnarkProof> ZcashSerialize for JoinSplitData<P> {
|
||||||
|
|
||||||
impl<P: ZkSnarkProof> ZcashDeserialize for Option<JoinSplitData<P>> {
|
impl<P: ZkSnarkProof> ZcashDeserialize for Option<JoinSplitData<P>> {
|
||||||
fn zcash_deserialize<R: io::Read>(mut reader: R) -> Result<Self, SerializationError> {
|
fn zcash_deserialize<R: io::Read>(mut reader: R) -> Result<Self, SerializationError> {
|
||||||
let num_joinsplits = reader.read_compactsize()?;
|
let joinsplits: Vec<sprout::JoinSplit<P>> = Vec::zcash_deserialize(&mut reader)?;
|
||||||
match num_joinsplits {
|
|
||||||
0 => Ok(None),
|
if joinsplits.is_empty() {
|
||||||
n => {
|
Ok(None)
|
||||||
let first = sprout::JoinSplit::zcash_deserialize(&mut reader)?;
|
} else {
|
||||||
let mut rest = Vec::with_capacity((n - 1) as usize);
|
let (first, rest) = joinsplits
|
||||||
for _ in 0..(n - 1) {
|
.split_first()
|
||||||
rest.push(sprout::JoinSplit::zcash_deserialize(&mut reader)?);
|
.expect("a non-empty Vec must have at least one entry");
|
||||||
}
|
let pub_key = reader.read_32_bytes()?.into();
|
||||||
let pub_key = reader.read_32_bytes()?.into();
|
let sig = reader.read_64_bytes()?.into();
|
||||||
let sig = reader.read_64_bytes()?.into();
|
Ok(Some(JoinSplitData {
|
||||||
Ok(Some(JoinSplitData {
|
first: first.clone(),
|
||||||
first,
|
rest: rest.to_vec(),
|
||||||
rest,
|
pub_key,
|
||||||
pub_key,
|
sig,
|
||||||
sig,
|
}))
|
||||||
}))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue