Skip to content

Commit

Permalink
Fix
Browse files Browse the repository at this point in the history
  • Loading branch information
chipshort committed Sep 26, 2024
1 parent 01c3c4e commit cf413c5
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 29 deletions.
7 changes: 7 additions & 0 deletions packages/vm/src/errors/communication_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ pub enum CommunicationError {
#[from]
source: RegionValidationError,
},
/// When the contract supplies invalid section data to the host. See also `decode_sections` [crate::sections::decode_sections].
#[error("Got an invalid section: {}", msg)]
InvalidSection { msg: String },
/// Whenever UTF-8 bytes cannot be decoded into a unicode string, e.g. in String::from_utf8 or str::from_utf8.
#[error("Cannot decode UTF8 bytes into string: {}", msg)]
InvalidUtf8 { msg: String },
Expand Down Expand Up @@ -56,6 +59,10 @@ impl CommunicationError {
CommunicationError::InvalidOrder { value }
}

pub(crate) fn invalid_section(msg: impl Into<String>) -> Self {
CommunicationError::InvalidSection { msg: msg.into() }
}

#[allow(dead_code)]
pub(crate) fn invalid_utf8(msg: impl ToString) -> Self {
CommunicationError::InvalidUtf8 {
Expand Down
6 changes: 3 additions & 3 deletions packages/vm/src/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -730,9 +730,9 @@ pub fn do_ed25519_batch_verify<
(EDDSA_PUBKEY_LEN + 4) * MAX_COUNT_ED25519_BATCH,
)?;

let messages = decode_sections(&messages);
let signatures = decode_sections(&signatures);
let public_keys = decode_sections(&public_keys);
let messages = decode_sections(&messages)?;
let signatures = decode_sections(&signatures)?;
let public_keys = decode_sections(&public_keys)?;

let gas_cost = if public_keys.len() == 1 {
&data.gas_config.ed25519_batch_verify_one_pubkey_cost
Expand Down
69 changes: 43 additions & 26 deletions packages/vm/src/sections.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
use crate::conversion::to_u32;
use crate::errors::VmResult;
use crate::{CommunicationError, VmResult};

/// Decodes sections of data into multiple slices.
///
/// Each encoded section is suffixed by a section length, encoded as big endian uint32.
///
/// See also: `encode_section`.
#[allow(dead_code)]
pub fn decode_sections(data: &[u8]) -> Vec<&[u8]> {
/// See also: [`encode_sections`].
pub fn decode_sections(data: &[u8]) -> Result<Vec<&[u8]>, CommunicationError> {
let mut result: Vec<&[u8]> = vec![];
let mut remaining_len = data.len();
while remaining_len >= 4 {
Expand All @@ -17,11 +16,20 @@ pub fn decode_sections(data: &[u8]) -> Vec<&[u8]> {
data[remaining_len - 2],
data[remaining_len - 1],
]) as usize;
result.push(&data[remaining_len - 4 - tail_len..remaining_len - 4]);
remaining_len -= 4 + tail_len;
let tail_len_idx = remaining_len - 4; // index of the first byte of the tail length
let section_start = tail_len_idx
.checked_sub(tail_len)
.ok_or_else(|| CommunicationError::invalid_section("section length overflow"))?;
result.push(&data[section_start..tail_len_idx]);
remaining_len = section_start;
}
if remaining_len > 0 {
return Err(CommunicationError::invalid_section(
"extra data outside of any section",
));
}
result.reverse();
result
Ok(result)
}

/// Encodes multiple sections of data into one vector.
Expand Down Expand Up @@ -57,52 +65,61 @@ mod tests {

#[test]
fn decode_sections_works_for_empty_sections() {
let dec = decode_sections(&[]);
let dec = decode_sections(&[]).unwrap();
assert_eq!(dec.len(), 0);
let dec = decode_sections(b"\0\0\0\0");
let dec = decode_sections(b"\0\0\0\0").unwrap();
assert_eq!(dec, &[&[0u8; 0]]);
let dec = decode_sections(b"\0\0\0\0\0\0\0\0");
let dec = decode_sections(b"\0\0\0\0\0\0\0\0").unwrap();
assert_eq!(dec, &[&[0u8; 0]; 2]);
let dec = decode_sections(b"\0\0\0\0\0\0\0\0\0\0\0\0");
let dec = decode_sections(b"\0\0\0\0\0\0\0\0\0\0\0\0").unwrap();
assert_eq!(dec, &[&[0u8; 0]; 3]);
// ignores "trailing" stuff
let dec = decode_sections(b"\0\0\0\0\0\0\0\0\0\0\0");
assert_eq!(dec, &[&[0u8; 0]; 2]);
}

#[test]
fn decode_sections_works_for_one_element() {
let dec = decode_sections(b"\xAA\0\0\0\x01");
let dec = decode_sections(b"\xAA\0\0\0\x01").unwrap();
assert_eq!(dec, &[vec![0xAA]]);
let dec = decode_sections(b"\xAA\xBB\0\0\0\x02");
let dec = decode_sections(b"\xAA\xBB\0\0\0\x02").unwrap();
assert_eq!(dec, &[vec![0xAA, 0xBB]]);
let dec = decode_sections(b"\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\0\0\x01\x15");
let dec = decode_sections(b"\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\0\0\x01\x15").unwrap();
assert_eq!(dec, &[vec![0x9D; 277]]);
}

#[test]
fn decode_sections_works_for_two_elements() {
let data = b"\xAA\0\0\0\x01\xBB\xCC\0\0\0\x02".to_vec();
assert_eq!(decode_sections(&data), &[vec![0xAA], vec![0xBB, 0xCC]]);
assert_eq!(
decode_sections(&data).unwrap(),
&[vec![0xAA], vec![0xBB, 0xCC]]
);
let data = b"\xDE\xEF\x62\0\0\0\x03\0\0\0\0".to_vec();
assert_eq!(decode_sections(&data), &[vec![0xDE, 0xEF, 0x62], vec![]]);
assert_eq!(
decode_sections(&data).unwrap(),
&[vec![0xDE, 0xEF, 0x62], vec![]]
);
let data = b"\0\0\0\0\xDE\xEF\x62\0\0\0\x03".to_vec();
assert_eq!(decode_sections(&data), &[vec![], vec![0xDE, 0xEF, 0x62]]);
assert_eq!(
decode_sections(&data).unwrap(),
&[vec![], vec![0xDE, 0xEF, 0x62]]
);
let data = b"\0\0\0\0\0\0\0\0".to_vec();
assert_eq!(decode_sections(&data), &[vec![0u8; 0], vec![]]);
assert_eq!(decode_sections(&data).unwrap(), &[vec![0u8; 0], vec![]]);
let data = b"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\0\0\x13\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\x9D\0\0\x01\x15".to_vec();
assert_eq!(decode_sections(&data), &[vec![0xFF; 19], vec![0x9D; 277]]);
assert_eq!(
decode_sections(&data).unwrap(),
&[vec![0xFF; 19], vec![0x9D; 277]]
);
}

#[test]
fn decode_sections_works_for_multiple_elements() {
let dec = decode_sections(b"\xAA\0\0\0\x01");
let dec = decode_sections(b"\xAA\0\0\0\x01").unwrap();
assert_eq!(dec, &[vec![0xAA]]);
let dec = decode_sections(b"\xAA\0\0\0\x01\xDE\xDE\0\0\0\x02");
let dec = decode_sections(b"\xAA\0\0\0\x01\xDE\xDE\0\0\0\x02").unwrap();
assert_eq!(dec, &[vec![0xAA], vec![0xDE, 0xDE]]);
let dec = decode_sections(b"\xAA\0\0\0\x01\xDE\xDE\0\0\0\x02\0\0\0\0");
let dec = decode_sections(b"\xAA\0\0\0\x01\xDE\xDE\0\0\0\x02\0\0\0\0").unwrap();
assert_eq!(dec, &[vec![0xAA], vec![0xDE, 0xDE], vec![]]);
let dec = decode_sections(b"\xAA\0\0\0\x01\xDE\xDE\0\0\0\x02\0\0\0\0\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\0\0\x13");
let dec = decode_sections(b"\xAA\0\0\0\x01\xDE\xDE\0\0\0\x02\0\0\0\0\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\0\0\x13").unwrap();
assert_eq!(dec, &[vec![0xAA], vec![0xDE, 0xDE], vec![], vec![0xFF; 19]]);
}

Expand Down

0 comments on commit cf413c5

Please sign in to comment.