Skip to content

Commit

Permalink
Merge pull request #105 from quilt/fix-push-0
Browse files Browse the repository at this point in the history
  • Loading branch information
lightclient committed Aug 3, 2022
2 parents 43a1f1f + 8574125 commit 7ebeaf2
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 5 deletions.
22 changes: 22 additions & 0 deletions etk-asm/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -787,6 +787,28 @@ mod tests {
Ok(())
}

#[test]
fn assemble_variable_push_too_large() {
let v = BigInt::from_bytes_be(Sign::Plus, &[1u8; 33]);

let mut asm = Assembler::new();
let err = asm
.push_all(vec![AbstractOp::Push(Terminal::Number(v).into())])
.unwrap_err();

assert_matches!(err, Error::ExpressionTooLarge { .. });
}

#[test]
fn assemble_variable_push_negative() {
let mut asm = Assembler::new();
let err = asm
.push_all(vec![AbstractOp::Push(Terminal::Number((-1).into()).into())])
.unwrap_err();

assert_matches!(err, Error::ExpressionNegative { .. });
}

#[test]
fn assemble_variable_push_const0() -> Result<(), Error> {
let mut asm = Assembler::new();
Expand Down
29 changes: 24 additions & 5 deletions etk-asm/src/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ mod types;

pub(crate) use self::error::Error;

use etk_ops::london::{Op, Operation};
use etk_ops::london::{Op, Operation, Push32};

pub use self::error::UnknownSpecifierError;
pub use self::expression::{Context, Expression, Terminal};
Expand All @@ -56,7 +56,7 @@ pub use self::macros::{
pub use self::types::Abstract;

use std::cmp::{Eq, PartialEq};
use std::convert::TryInto;
use std::convert::{TryFrom, TryInto};
use std::fmt;

use snafu::{ensure, ResultExt};
Expand Down Expand Up @@ -200,13 +200,32 @@ impl AbstractOp {
match self {
Self::Op(op) => op.concretize(ctx),
Self::Push(imm) => {
let res = imm
let value = imm
.tree
.eval_with_context(ctx)
.context(error::ContextIncomplete)?;
let size = std::cmp::max(1, (res.bits() + 8 - 1) / 8);

let (sign, bytes) = value.to_bytes_be();

ensure!(
sign != num_bigint::Sign::Minus,
error::ExpressionNegative { value }
);

if bytes.len() > 32 {
// TODO: Fix hack to get a TryFromSliceError.
let err = <[u8; 32]>::try_from(bytes.as_slice())
.context(error::ExpressionTooLarge {
value,
spec: Push32(()),
})
.unwrap_err();
return Err(err);
}

let size = std::cmp::max(1, (value.bits() + 8 - 1) / 8);
let spec = Op::<()>::push(size.try_into().unwrap()).unwrap();
let bytes = res.to_bytes_be().1;

let start = bytes.len() + 1 - spec.size();
AbstractOp::new(spec.with(&bytes[start..]).unwrap()).concretize(ctx)
}
Expand Down

0 comments on commit 7ebeaf2

Please sign in to comment.