Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
18 changes: 18 additions & 0 deletions executor/src/phase/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,10 @@ impl ExecutorState<'_> {

// Action list itself is ok.
res.action_phase.valid = true;
let pre_action_balance = ctx
.received_message
.as_ref()
.map(|msg| msg.balance_remaining.clone());

// Execute actions.
let mut action_ctx = ActionContext {
Expand Down Expand Up @@ -231,6 +235,13 @@ impl ExecutorState<'_> {
// Apply flags.
res.bounce |= action_ctx.need_bounce_on_fail;

if self.config.global.version >= 14
&& let Some(msg) = action_ctx.received_message.as_deref_mut()
&& let Some(balance) = pre_action_balance
{
msg.balance_remaining = balance;
}

// Ignore all other action.
return Ok(res);
}
Expand Down Expand Up @@ -268,6 +279,13 @@ impl ExecutorState<'_> {
)?;

// Apply flags.
if self.config.global.version >= 14
&& let Some(msg) = action_ctx.received_message.as_deref_mut()
&& let Some(balance) = pre_action_balance
{
msg.balance_remaining = balance;
}

res.bounce |= action_ctx.need_bounce_on_fail;
res.action_phase.result_code = ResultCode::StateOutOfLimits as i32;
res.state_exceeds_limits = true;
Expand Down
2 changes: 1 addition & 1 deletion executor/src/phase/compute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ impl ExecutorState<'_> {

// NOTE: Not all versions change the smc info, so we need to bump
// this value manually.
let real_version = tycho_vm::VmVersion::Ton(12);
let real_version = tycho_vm::VmVersion::Ton(14);

if let Some(inspector) = ctx.inspector.as_deref_mut()
&& let Some(modify_smc_info) = inspector.modify_smc_info.as_deref_mut()
Expand Down
18 changes: 14 additions & 4 deletions vm/src/cont.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,15 +197,25 @@ impl ControlRegs {
}

pub fn define(&mut self, i: usize, value: RcStackValue) -> VmResult<()> {
self.define_ext(i, value, false)
}

pub fn define_ext(&mut self, i: usize, value: RcStackValue, silent: bool) -> VmResult<()> {
if i < Self::CONT_REG_COUNT {
let cont = ok!(value.into_cont());
vm_ensure!(self.c[i].is_none(), ControlRegisterRedefined);
self.c[i] = Some(cont);
if self.c[i].is_none() {
self.c[i] = Some(cont);
} else {
vm_ensure!(silent, ControlRegisterRedefined);
}
} else if Self::DATA_REG_RANGE.contains(&i) {
let cell = ok!(value.into_cell());
let d = &mut self.d[i - Self::DATA_REG_OFFSET];
vm_ensure!(d.is_none(), ControlRegisterRedefined);
*d = Some(SafeRc::unwrap_or_clone(cell));
if d.is_none() {
*d = Some(SafeRc::unwrap_or_clone(cell));
} else {
vm_ensure!(silent, ControlRegisterRedefined);
}
} else if i == 7 {
let tuple = ok!(value.into_tuple());

Expand Down
33 changes: 26 additions & 7 deletions vm/src/instr/arithops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::cmp::Ordering;

use num_bigint::{BigInt, Sign};
use num_integer::Integer;
use num_traits::Zero;
use num_traits::{ToPrimitive, Zero};
#[cfg(feature = "dump")]
use tycho_types::prelude::*;
use tycho_vm_proc::vm_module;
Expand Down Expand Up @@ -353,11 +353,18 @@ impl ArithOps {

let stack = SafeRc::make_mut(&mut st.stack);
let y = match y {
Some(y) => y,
None => ok!(stack.pop_smallint_range(0, 256)),
Some(y) => Some(y),
None if quiet && st.version.is_ton(14..) => {
if let Some(item) = ok!(stack.pop_int_or_nan()) {
item.to_u32().filter(|item| (0..=256).contains(item))
} else {
None
}
}
None => Some(ok!(stack.pop_smallint_range(0, 256))),
};

if y == 0 {
if y == Some(0) {
round_mode = RoundMode::Floor;
}
let w = if add {
Expand All @@ -366,8 +373,14 @@ impl ArithOps {
None
};

match ok!(stack.pop_int_or_nan()) {
Some(mut x) => match operation {
match (ok!(stack.pop_int_or_nan()), y) {
(_, None) if quiet => {
ok!(stack.push_nan());
if let Operation::RShiftMod = operation {
ok!(stack.push_nan());
}
}
(Some(mut x), Some(y)) => match operation {
Operation::RShift => {
let res = int_rshift(&x, y, round_mode);
ok!(stack.push_raw_int(update_or_new_rc(x, res), quiet));
Expand All @@ -394,7 +407,7 @@ impl ArithOps {
ok!(stack.push_raw_int(SafeRc::new(r), quiet));
}
},
_ if quiet => {
(None, _) if quiet => {
ok!(stack.push_nan());
if let Operation::RShiftMod = operation {
ok!(stack.push_nan());
Expand Down Expand Up @@ -1264,6 +1277,8 @@ mod tests {
assert_run_vm!("MODPOW2", [nan, int 3] => [int 0], exit_code: 4);
assert_run_vm!("QUIET MODPOW2", [int 5, int 2] => [int 1]);
assert_run_vm!("QUIET MODPOW2", [nan, int 3] => [nan]);
assert_run_vm!("QUIET MODPOW2", [int 5, nan] => [nan]);
assert_run_vm!("QUIET MODPOW2", [int 5, int 257] => [nan]);

assert_run_vm!("RSHIFTMOD", [int 5, int 2] => [int 1, int 1]);
assert_run_vm!("RSHIFTMOD", [int 5, int 0] => [int 5, int 0]);
Expand All @@ -1273,6 +1288,8 @@ mod tests {
assert_run_vm!("RSHIFTMOD", [nan, int 3] => [int 0], exit_code: 4);
assert_run_vm!("QUIET RSHIFTMOD", [int 5, int 2] => [int 1, int 1]);
assert_run_vm!("QUIET RSHIFTMOD", [nan, int 3] => [nan, nan]);
assert_run_vm!("QUIET RSHIFTMOD", [int 5, nan] => [nan, nan]);
assert_run_vm!("QUIET RSHIFTMOD", [int 5, int 257] => [nan, nan]);

assert_run_vm!("ADDRSHIFTMOD", [int 3, int 2, int 2] => [int 1, int 1]);
assert_run_vm!("ADDRSHIFTMOD", [int 3, int 2, int 0] => [int 5, int 0]);
Expand All @@ -1284,6 +1301,8 @@ mod tests {
assert_run_vm!("QUIET ADDRSHIFTMOD", [int 3, int 2, int 2] => [int 1, int 1]);
assert_run_vm!("QUIET ADDRSHIFTMOD", [nan, int 1, int 3] => [nan, nan]);
assert_run_vm!("QUIET ADDRSHIFTMOD", [int 1, nan, int 3] => [nan, nan]);
assert_run_vm!("QUIET ADDRSHIFTMOD", [int 3, int 2, nan] => [nan, nan]);
assert_run_vm!("QUIET ADDRSHIFTMOD", [int 3, int 2, int 257] => [nan, nan]);
}

// TODO: Add more tests
Expand Down
45 changes: 38 additions & 7 deletions vm/src/instr/contops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -748,7 +748,9 @@ impl ContOps {
let stack = SafeRc::make_mut(&mut st.stack);
let mut cont = ok!(stack.pop_cont());
let value = ok!(stack.pop());
ok!(force_cdata(&mut cont).save.define(i as _, value));
ok!(force_cdata(&mut cont)
.save
.define_ext(i as _, value, st.version.is_ton(14..)));
ok!(stack.push_raw(cont));
Ok(0)
}
Expand All @@ -758,7 +760,9 @@ impl ContOps {
vm_ensure!(ControlRegs::is_valid_idx(i as _), InvalidOpcode);
let cont = st.cr.c[0].as_mut().expect("c0 should always be set");
let value = ok!(SafeRc::make_mut(&mut st.stack).pop());
ok!(force_cdata(cont).save.define(i as _, value));
ok!(force_cdata(cont)
.save
.define_ext(i as _, value, st.version.is_ton(14..)));
Ok(0)
}

Expand All @@ -768,7 +772,9 @@ impl ContOps {
// TODO: Check if c1 is always set
let cont = st.cr.c[1].as_mut().expect("c1 should always be set");
let value = ok!(SafeRc::make_mut(&mut st.stack).pop());
ok!(force_cdata(cont).save.define(i as _, value));
ok!(force_cdata(cont)
.save
.define_ext(i as _, value, st.version.is_ton(14..)));
Ok(0)
}

Expand Down Expand Up @@ -818,7 +824,9 @@ impl ContOps {
.get_as_stack_value(i as _)
.unwrap_or_else(Stack::make_null);

ok!(force_cdata(&mut c0).save.define(i as _, value));
ok!(force_cdata(&mut c0)
.save
.define_ext(i as _, value, st.version.is_ton(14..)));
st.cr.c[0] = Some(c0);
Ok(0)
}
Expand All @@ -835,7 +843,9 @@ impl ContOps {
.get_as_stack_value(i as _)
.unwrap_or_else(Stack::make_null);

ok!(force_cdata(&mut c1).save.define(i as _, value));
ok!(force_cdata(&mut c1)
.save
.define_ext(i as _, value, st.version.is_ton(14..)));
st.cr.c[1] = Some(c1);
Ok(0)
}
Expand Down Expand Up @@ -895,7 +905,9 @@ impl ContOps {
);
let mut cont = ok!(stack.pop_cont());
let value = ok!(stack.pop());
ok!(force_cdata(&mut cont).save.define(idx, value));
ok!(force_cdata(&mut cont)
.save
.define_ext(idx, value, st.version.is_ton(14..)));
ok!(stack.push_raw(cont));
Ok(0)
}
Expand Down Expand Up @@ -925,7 +937,9 @@ impl ContOps {
actual: StackValueType::Null as _
})
};
ok!(force_cdata(&mut cont).save.define(i, st_value));
ok!(force_cdata(&mut cont)
.save
.define_ext(i, st_value, st.version.is_ton(14..)));
}

ok!(stack.push_raw(cont));
Expand Down Expand Up @@ -2197,6 +2211,23 @@ mod tests {
);
}

#[test]
#[traced_test]
fn control_savelist_redefinition() {
assert_run_vm!(
r#"
PUSHREF x{1111}
PUSHCONT { PUSH c4 CTOS }
SETCONTCTR c4
PUSHREF x{2222}
SWAP
SETCONTCTR c4
EXECUTE
"#,
[] => [slice make_slice(0x1111_u16)]
);
}

#[test]
#[traced_test]
fn runvm_simple() {
Expand Down
53 changes: 53 additions & 0 deletions vm/src/instr/cryptops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,13 @@ impl CryptOps {
st.gas.try_consume_check_signature_gas()?;

let is_valid = 'valid: {
if st.version.is_ton(14..)
&& key_bytes[0] == 1
&& key_bytes[1..].iter().all(|v| *v == 0)
{
break 'valid false;
}

let Some(pubkey) =
ed25519::PublicKey::from_bytes(key_bytes.as_slice().try_into().unwrap())
else {
Expand Down Expand Up @@ -681,6 +688,52 @@ mod tests {
Ok(())
}

#[test]
#[traced_test]
fn chksign_rejects_identity_pubkey_v14() {
use crate::VmVersion;
let data = [];
let mut signature = [0; 64];
signature[0] = 1;
let mut identity = [0; 32];
identity[0] = 1;

assert_run_vm!(
"CHKSIGNS",
state: |st| st.version = VmVersion::Ton(13),
[
raw build_slice(data),
raw build_slice(signature),
raw build_int(identity),
] => [int -1]
);
assert_run_vm!(
"CHKSIGNS",
[
raw build_slice(data),
raw build_slice(signature),
raw build_int(identity),
] => [int 0]
);
assert_run_vm!(
"CHKSIGNU",
state: |st| st.version = VmVersion::Ton(13),
[
int 0,
raw build_slice(signature),
raw build_int(identity),
] => [int -1]
);
assert_run_vm!(
"CHKSIGNU",
[
int 0,
raw build_slice(signature),
raw build_int(identity),
] => [int 0]
);
}

#[test]
#[traced_test]
fn signdomain_stack_only() {
Expand Down
Loading