From f03f6ce7cad7c367f9ad93157ee63a7eb6483820 Mon Sep 17 00:00:00 2001 From: SpyCheese Date: Tue, 17 Dec 2024 11:16:43 +0300 Subject: [PATCH] Fix check_underflow in some instructions --- crypto/vm/dictops.cpp | 4 ++-- crypto/vm/tonops.cpp | 10 +++++++++- doc/GlobalVersions.md | 5 ++++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/crypto/vm/dictops.cpp b/crypto/vm/dictops.cpp index d0ea8daa..02f26fdd 100644 --- a/crypto/vm/dictops.cpp +++ b/crypto/vm/dictops.cpp @@ -566,7 +566,7 @@ int exec_dict_getnear(VmState* st, unsigned args) { int exec_pfx_dict_set(VmState* st, Dictionary::SetMode mode, const char* name) { Stack& stack = st->get_stack(); VM_LOG(st) << "execute PFXDICT" << name; - stack.check_underflow(3); + stack.check_underflow(st->get_global_version() >= 9 ? 4 : 3); int n = stack.pop_smallint_range(PrefixDictionary::max_key_bits); PrefixDictionary dict{stack.pop_maybe_cell(), n}; auto key_slice = stack.pop_cellslice(); @@ -580,7 +580,7 @@ int exec_pfx_dict_set(VmState* st, Dictionary::SetMode mode, const char* name) { int exec_pfx_dict_delete(VmState* st) { Stack& stack = st->get_stack(); VM_LOG(st) << "execute PFXDICTDEL\n"; - stack.check_underflow(2); + stack.check_underflow(st->get_global_version() >= 9 ? 3 : 2); int n = stack.pop_smallint_range(PrefixDictionary::max_key_bits); PrefixDictionary dict{stack.pop_maybe_cell(), n}; auto key_slice = stack.pop_cellslice(); diff --git a/crypto/vm/tonops.cpp b/crypto/vm/tonops.cpp index 6c698df4..d134f80b 100644 --- a/crypto/vm/tonops.cpp +++ b/crypto/vm/tonops.cpp @@ -279,6 +279,7 @@ int exec_get_global_id(VmState* st) { int exec_get_gas_fee(VmState* st) { VM_LOG(st) << "execute GETGASFEE"; Stack& stack = st->get_stack(); + stack.check_underflow(st->get_global_version() >= 9 ? 2 : 0); bool is_masterchain = stack.pop_bool(); td::uint64 gas = stack.pop_long_range(std::numeric_limits::max(), 0); block::GasLimitsPrices prices = util::get_gas_prices(get_unpacked_config_tuple(st), is_masterchain); @@ -289,6 +290,7 @@ int exec_get_gas_fee(VmState* st) { int exec_get_storage_fee(VmState* st) { VM_LOG(st) << "execute GETSTORAGEFEE"; Stack& stack = st->get_stack(); + stack.check_underflow(st->get_global_version() >= 9 ? 4 : 0); bool is_masterchain = stack.pop_bool(); td::int64 delta = stack.pop_long_range(std::numeric_limits::max(), 0); td::uint64 bits = stack.pop_long_range(std::numeric_limits::max(), 0); @@ -302,6 +304,7 @@ int exec_get_storage_fee(VmState* st) { int exec_get_forward_fee(VmState* st) { VM_LOG(st) << "execute GETFORWARDFEE"; Stack& stack = st->get_stack(); + stack.check_underflow(st->get_global_version() >= 9 ? 3 : 0); bool is_masterchain = stack.pop_bool(); td::uint64 bits = stack.pop_long_range(std::numeric_limits::max(), 0); td::uint64 cells = stack.pop_long_range(std::numeric_limits::max(), 0); @@ -320,6 +323,7 @@ int exec_get_precompiled_gas(VmState* st) { int exec_get_original_fwd_fee(VmState* st) { VM_LOG(st) << "execute GETORIGINALFWDFEE"; Stack& stack = st->get_stack(); + stack.check_underflow(st->get_global_version() >= 9 ? 2 : 0); bool is_masterchain = stack.pop_bool(); td::RefInt256 fwd_fee = stack.pop_int_finite(); if (fwd_fee->sgn() < 0) { @@ -333,6 +337,7 @@ int exec_get_original_fwd_fee(VmState* st) { int exec_get_gas_fee_simple(VmState* st) { VM_LOG(st) << "execute GETGASFEESIMPLE"; Stack& stack = st->get_stack(); + stack.check_underflow(st->get_global_version() >= 9 ? 2 : 0); bool is_masterchain = stack.pop_bool(); td::uint64 gas = stack.pop_long_range(std::numeric_limits::max(), 0); block::GasLimitsPrices prices = util::get_gas_prices(get_unpacked_config_tuple(st), is_masterchain); @@ -343,6 +348,7 @@ int exec_get_gas_fee_simple(VmState* st) { int exec_get_forward_fee_simple(VmState* st) { VM_LOG(st) << "execute GETFORWARDFEESIMPLE"; Stack& stack = st->get_stack(); + stack.check_underflow(st->get_global_version() >= 9 ? 3 : 0); bool is_masterchain = stack.pop_bool(); td::uint64 bits = stack.pop_long_range(std::numeric_limits::max(), 0); td::uint64 cells = stack.pop_long_range(std::numeric_limits::max(), 0); @@ -373,6 +379,7 @@ void register_ton_config_ops(OpcodeTable& cp0) { .insert(OpcodeInstr::mksimple(0xf833, 16, "CONFIGOPTPARAM", std::bind(exec_get_config_param, _1, true))) .insert(OpcodeInstr::mksimple(0xf83400, 24, "PREVMCBLOCKS", std::bind(exec_get_prev_blocks_info, _1, 0, "PREVMCBLOCKS"))->require_version(4)) .insert(OpcodeInstr::mksimple(0xf83401, 24, "PREVKEYBLOCK", std::bind(exec_get_prev_blocks_info, _1, 1, "PREVKEYBLOCK"))->require_version(4)) + .insert(OpcodeInstr::mksimple(0xf83402, 24, "PREVMCBLOCKS_100", std::bind(exec_get_prev_blocks_info, _1, 2, "PREVMCBLOCKS_100"))->require_version(9)) .insert(OpcodeInstr::mksimple(0xf835, 16, "GLOBALID", exec_get_global_id)->require_version(4)) .insert(OpcodeInstr::mksimple(0xf836, 16, "GETGASFEE", exec_get_gas_fee)->require_version(6)) .insert(OpcodeInstr::mksimple(0xf837, 16, "GETSTORAGEFEE", exec_get_storage_fee)->require_version(6)) @@ -538,9 +545,10 @@ int exec_hash_ext(VmState* st, unsigned args) { VM_LOG(st) << "execute HASHEXT" << (append ? "A" : "") << (rev ? "R" : "") << " " << (hash_id == 255 ? -1 : hash_id); Stack& stack = st->get_stack(); if (hash_id == 255) { + stack.check_underflow(st->get_global_version() >= 9 ? 2 : 0); hash_id = stack.pop_smallint_range(254); } - int cnt = stack.pop_smallint_range(stack.depth() - 1); + int cnt = stack.pop_smallint_range(stack.depth() - 1 - (st->get_global_version() >= 9 ? (int)append : 0)); Hasher hasher{hash_id}; size_t total_bits = 0; long long gas_consumed = 0; diff --git a/doc/GlobalVersions.md b/doc/GlobalVersions.md index 5db1ab76..11b9b68c 100644 --- a/doc/GlobalVersions.md +++ b/doc/GlobalVersions.md @@ -3,6 +3,7 @@ Global version is a parameter specified in `ConfigParam 8` ([block.tlb](https:// Various features are enabled depending on the global version. ## Version 4 +New features of version 4 are desctibed in detail in [the documentation](https://docs.ton.org/v3/documentation/tvm/changelog/tvm-upgrade-2023-07). ### New TVM instructions * `PREVMCBLOCKS`, `PREVKEYBLOCK` @@ -122,4 +123,6 @@ Operations for working with Merkle proofs, where cells can have non-zero level a ### Other changes - Fix `RAWRESERVE` action with flag `4` (use original balance of the account) by explicitly setting `original_balance` to `balance - msg_balance_remaining`. - Previously it did not work if storage fee was greater than the original balance. -- Jumps to nested continuations of depth more than 8 consume 1 gas for eact subsequent continuation (this does not affect most of TVM code). \ No newline at end of file +- Jumps to nested continuations of depth more than 8 consume 1 gas for eact subsequent continuation (this does not affect most of TVM code). +- Fix exception code in some TVM instructions: now `stk_und` has priority over other error codes. + - `PFXDICTADD`, `PFXDICTSET`, `PFXDICTREPLACE`, `PFXDICTDEL`, `GETGASFEE`, `GETSTORAGEFEE`, `GETFORWARDFEE`, `GETORIGINALFWDFEE`, `GETGASFEESIMPLE`, `GETFORWARDFEESIMPLE`, `HASHEXT` \ No newline at end of file