Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deserialization fixes #735

Merged
merged 19 commits into from
Apr 3, 2022
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions algorithms/src/merkle_tree/merkle_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,16 +125,22 @@ impl<P: MerkleParameters> FromBytes for MerklePath<P> {
// If you are seeing this message, please be proactive in bringing it up :)
let parameters = {
let setup_message_length: u64 = FromBytes::read_le(&mut reader)?;
if setup_message_length > 1024 * 1024 * 10 {
howardwu marked this conversation as resolved.
Show resolved Hide resolved
return Err(std::io::ErrorKind::InvalidData.into());
}

let mut setup_message_bytes = vec![0u8; setup_message_length as usize];
reader.read_exact(&mut setup_message_bytes)?;
let setup_message =
String::from_utf8(setup_message_bytes).expect("Failed to parse setup message for Merkle parameters");
let setup_message = String::from_utf8(setup_message_bytes).map_err(|_| std::io::ErrorKind::InvalidData)?;

Arc::new(P::setup(&setup_message))
};

let path_length: u64 = FromBytes::read_le(&mut reader)?;
if path_length > 1024 * 1024 * 10 {
return Err(std::io::ErrorKind::InvalidData.into());
}

let mut path = Vec::with_capacity(path_length as usize);
for _ in 0..path_length {
path.push(FromBytes::read_le(&mut reader)?);
Expand Down
3 changes: 2 additions & 1 deletion dpc/src/posw/proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ impl<N: Network> PoSWProof<N> {
match self {
Self::NonHiding(proof) => {
// Ensure the proof is valid.
if !<<N as Network>::PoSWSNARK as SNARK>::verify(verifying_key, &inputs.to_vec(), proof).unwrap() {
let check = <<N as Network>::PoSWSNARK as SNARK>::verify(verifying_key, &inputs.to_vec(), proof);
if check.is_err() || !check.unwrap() {
#[cfg(debug_assertions)]
eprintln!("PoSW proof verification failed");
return false;
Expand Down
6 changes: 6 additions & 0 deletions dpc/src/record/ciphertext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,12 @@ impl<N: Network> FromBytes for Ciphertext<N> {
let record_view_key_commitment = N::RecordViewKeyCommitment::read_le(&mut reader)?;

let num_elements: u32 = FromBytes::read_le(&mut reader)?;

// Reject values greater than the expected maximum count.
if num_elements > 1000 {
return Err(std::io::ErrorKind::InvalidData.into());
}

let mut record_elements = Vec::with_capacity(num_elements as usize);
for _ in 0..num_elements {
record_elements.push(FromBytes::read_le(&mut reader)?);
Expand Down
6 changes: 4 additions & 2 deletions dpc/src/transaction/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,8 +348,10 @@ impl<N: Network> FromBytes for Transaction<N> {
transitions.push(FromBytes::read_le(&mut reader)?);
}

Ok(Self::from(input_circuit_id, output_circuit_id, ledger_root, transitions)
.expect("Failed to deserialize a transaction"))
let tx = Self::from(input_circuit_id, output_circuit_id, ledger_root, transitions)
.map_err(|_| std::io::ErrorKind::InvalidData)?;

Ok(tx)
}
}

Expand Down
12 changes: 10 additions & 2 deletions dpc/src/transaction/transition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,12 +396,20 @@ impl<N: Network> FromBytes for Transition<N> {
let transition_id: N::TransitionID = FromBytes::read_le(&mut reader)?;

let num_input_records: u32 = FromBytes::read_le(&mut reader)?;
if num_input_records > 1000 {
return Err(std::io::ErrorKind::InvalidData.into());
}

let mut serial_numbers = Vec::<N::SerialNumber>::with_capacity(num_input_records as usize);
for _ in 0..num_input_records {
serial_numbers.push(FromBytes::read_le(&mut reader)?);
}

let num_output_records: u32 = FromBytes::read_le(&mut reader)?;
if num_output_records > 1000 {
return Err(std::io::ErrorKind::InvalidData.into());
}

let mut ciphertexts = Vec::<N::RecordCiphertext>::with_capacity(num_output_records as usize);
for _ in 0..num_output_records {
ciphertexts.push(FromBytes::read_le(&mut reader)?);
Expand Down Expand Up @@ -429,7 +437,7 @@ impl<N: Network> FromBytes for Transition<N> {

let execution: Execution<N> = FromBytes::read_le(&mut reader)?;

Ok(Self::from(
Self::from(
transition_id,
serial_numbers,
ciphertexts,
Expand All @@ -440,7 +448,7 @@ impl<N: Network> FromBytes for Transition<N> {
events,
execution,
)
.expect("Failed to deserialize a transition from bytes"))
.map_err(|_| std::io::ErrorKind::InvalidData.into())
}
}

Expand Down
2 changes: 1 addition & 1 deletion dpc/src/virtual_machine/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ impl<N: Network> FromBytes for Event<N> {
Ok(Self::RecordViewKey(index, record_view_key))
}
2 => Ok(Self::Operation(FromBytes::read_le(&mut reader)?)),
_ => unreachable!("Invalid event ID during deserialization"),
_ => Err(std::io::ErrorKind::InvalidData.into()),
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions dpc/src/virtual_machine/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,12 +145,20 @@ impl<N: Network> FromBytes for Execution<N> {
};

let num_input_proofs: u32 = FromBytes::read_le(&mut reader)?;
if num_input_proofs > 1000 {
return Err(std::io::ErrorKind::InvalidData.into());
}

let mut input_proofs = Vec::with_capacity(num_input_proofs as usize);
for _ in 0..num_input_proofs {
input_proofs.push(FromBytes::read_le(&mut reader)?);
}

let num_output_proofs: u32 = FromBytes::read_le(&mut reader)?;
if num_output_proofs > 1000 {
return Err(std::io::ErrorKind::InvalidData.into());
}

let mut output_proofs = Vec::with_capacity(num_output_proofs as usize);
for _ in 0..num_output_proofs {
output_proofs.push(FromBytes::read_le(&mut reader)?);
Expand Down
2 changes: 1 addition & 1 deletion dpc/src/virtual_machine/operation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ impl<N: Network> FromBytes for Operation<N> {
let function_inputs = FromBytes::read_le(&mut reader)?;
Ok(Self::Evaluate(function_id, function_inputs))
}
_ => unreachable!("Invalid operation during deserialization"),
_ => Err(std::io::ErrorKind::InvalidData.into()),
}
}
}
Expand Down
12 changes: 11 additions & 1 deletion utilities/src/serialize/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub use crate::{
};
use crate::{serialize::traits::*, SerializationError};

use std::{borrow::Cow, collections::BTreeMap, rc::Rc, sync::Arc};
use std::{borrow::Cow, collections::BTreeMap, mem, rc::Rc, sync::Arc};

impl CanonicalSerialize for bool {
#[inline]
Expand Down Expand Up @@ -294,6 +294,11 @@ impl<T: CanonicalDeserialize> CanonicalDeserialize for Vec<T> {
#[inline]
fn deserialize<R: Read>(reader: &mut R) -> Result<Self, SerializationError> {
let len = u64::deserialize(reader)?;

if mem::size_of::<T>().saturating_mul(len as usize) > 1024 * 1024 * 1024 {
return Err(SerializationError::InvalidData);
}

let mut values = Vec::with_capacity(len as usize);
for _ in 0..len {
values.push(T::deserialize(reader)?);
Expand All @@ -304,6 +309,11 @@ impl<T: CanonicalDeserialize> CanonicalDeserialize for Vec<T> {
#[inline]
fn deserialize_uncompressed<R: Read>(reader: &mut R) -> Result<Self, SerializationError> {
let len = u64::deserialize(reader)?;

if mem::size_of::<T>().saturating_mul(len as usize) > 1024 * 1024 * 1024 {
return Err(SerializationError::InvalidData);
}

let mut values = Vec::with_capacity(len as usize);
for _ in 0..len {
values.push(T::deserialize_uncompressed(reader)?);
Expand Down