Skip to content

Commit

Permalink
Add protobuf base128 varint decoding
Browse files Browse the repository at this point in the history
  • Loading branch information
maurolacy committed Oct 21, 2021
1 parent ad1cc93 commit 9c6ad8f
Showing 1 changed file with 36 additions and 12 deletions.
48 changes: 36 additions & 12 deletions packages/cw0/src/parse_reply.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,37 @@ pub struct MsgExecuteContractResponse {
pub data: Option<Binary>,
}

/// Base128 varint decoding.
/// Up to 9 bytes of varints as a practical limit (https://github.com/multiformats/unsigned-varint#practical-maximum-of-9-bytes-for-security)
/// The remaining of the data is kept in the data parameter.
fn parse_protobuf_varint(data: &mut Vec<u8>, field_number: u8) -> Result<usize, ParseReplyError> {
let mut len: u64 = 0;
let mut i = 0;
while i < 9 {
if data.len() == i {
return Err(ParseReplyError::ParseFailure(format!(
"failed to decode Protobuf message: field #{}: varint too short",
field_number
)));
}
len <<= 7;
len += (data[i] & 0x7f) as u64;
if data[i] & 0x80 == 0 {
break;
}
i += 1;
}
if i == 9 {
return Err(ParseReplyError::ParseFailure(format!(
"failed to decode Protobuf message: field #{}: varint too long",
field_number
)));
}
*data = data.split_off(i + 1);

Ok(len as usize) // Gently fall back to the arch's max addressable size
}

/// Helper function to parse length-prefixed protobuf fields.
/// The remaining of the data is kept in the data parameter.
fn parse_protobuf_length_prefixed(
Expand All @@ -41,24 +72,17 @@ fn parse_protobuf_length_prefixed(
field_number, wire_type
)));
}
if rest_1.is_empty() {
return Err(ParseReplyError::ParseFailure(format!(
"failed to decode Protobuf message: field #{}: message too short",
field_number
)));
}
let mut rest_2 = rest_1.split_off(1);
let len = rest_1[0] as usize;
if rest_2.len() < len {

let len = parse_protobuf_varint(&mut rest_1, field_number)?;
if rest_1.len() < len {
return Err(ParseReplyError::ParseFailure(format!(
"failed to decode Protobuf message: field #{}: message too short",
field_number
)));
}
let rest_3 = rest_2.split_off(len);
*data = rest_1.split_off(len);

*data = rest_3;
Ok(rest_2)
Ok(rest_1)
}

fn parse_protobuf_string(data: &mut Vec<u8>, field_number: u8) -> Result<String, ParseReplyError> {
Expand Down

0 comments on commit 9c6ad8f

Please sign in to comment.