Fix buffer overrun in eth abi encoder
@@ -16,6 +16,7 @@ use super::{Binary, ReturnCode};
/// 3) EncoderBuilder::finish() generates the code which encodes the data to the pointer provided. The
/// called should ensure there is enough space.
pub struct EncoderBuilder<'a, 'b> {
+ packed_length: IntValue<'a>,
length: IntValue<'a>,
offset: IntValue<'a>,
load_args: bool,
@@ -62,6 +63,8 @@ impl<'a, 'b> EncoderBuilder<'a, 'b> {
);
}
+ let packed_length = length;
+
// now add the dynamic lengths
for (i, arg) in args.iter().enumerate() {
length = binary.builder.build_int_add(
@@ -79,6 +82,7 @@ impl<'a, 'b> EncoderBuilder<'a, 'b> {
}
EncoderBuilder {
+ packed_length,
length,
offset,
load_args,
@@ -654,6 +658,7 @@ impl<'a, 'b> EncoderBuilder<'a, 'b> {
// We use a little trick here. The length might or might not include the selector.
// The length will be a multiple of 32 plus the selector (4). So by dividing by 8,
// we lose the selector.
+ if !self.args.is_empty() {
binary.builder.build_call(
binary.module.get_function("__bzero8").unwrap(),
&[
@@ -661,7 +666,11 @@ impl<'a, 'b> EncoderBuilder<'a, 'b> {
binary
.builder
.build_int_unsigned_div(
+ binary.builder.build_int_sub(
self.length,
+ self.packed_length,
+ "dyn_len",
+ ),
binary.context.i32_type().const_int(8, false),
"",
)
@@ -690,6 +699,7 @@ impl<'a, 'b> EncoderBuilder<'a, 'b> {
);
}
}
+ }
/// Recursively encode a value in arg. The load argument specifies if the arg is a pointer
/// to the value, or the value itself. The fixed pointer points to the fixed, non-dynamic part
