Skip to content

Commit

Permalink
Disallow recursive library cells (#868)
Browse files Browse the repository at this point in the history
* Disallow recursive library cells

* Stop emulation of external messages on accept

---------

Co-authored-by: SpyCheese <[email protected]>
  • Loading branch information
EmelyanenkoK and SpyCheese authored Jan 22, 2024
1 parent 128a85b commit 42d4c05
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 0 deletions.
1 change: 1 addition & 0 deletions crypto/block/transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1559,6 +1559,7 @@ bool Transaction::prepare_compute_phase(const ComputePhaseConfig& cfg) {
vm.set_global_version(cfg.global_version);
vm.set_c7(prepare_vm_c7(cfg)); // tuple with SmartContractInfo
vm.set_chksig_always_succeed(cfg.ignore_chksig);
vm.set_stop_on_accept_message(cfg.stop_on_accept_message);
// vm.incr_stack_trace(1); // enable stack dump after each step

LOG(DEBUG) << "starting VM";
Expand Down
1 change: 1 addition & 0 deletions crypto/block/transaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ struct ComputePhaseConfig {
std::unique_ptr<vm::Dictionary> suspended_addresses;
SizeLimitsConfig size_limits;
int vm_log_verbosity = 0;
bool stop_on_accept_message = false;

ComputePhaseConfig() : gas_price(0), gas_limit(0), special_gas_limit(0), gas_credit(0) {
compute_threshold();
Expand Down
31 changes: 31 additions & 0 deletions crypto/vm/cellops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -892,6 +892,37 @@ int exec_load_special_cell(VmState* st, bool quiet) {
Stack& stack = st->get_stack();
VM_LOG(st) << "execute XLOAD" << (quiet ? "Q" : "");
auto cell = stack.pop_cell();
auto r_loaded_cell = cell->load_cell();
if (r_loaded_cell.is_error()) {
if (quiet) {
stack.push_bool(false);
return 0;
} else {
throw VmError{Excno::cell_und, "failed to load cell"};
}
}
auto loaded_cell = r_loaded_cell.move_as_ok();
if (loaded_cell.data_cell->is_special()) {
if (loaded_cell.data_cell->special_type() != CellTraits::SpecialType::Library) {
if (quiet) {
stack.push_bool(false);
return 0;
} else {
throw VmError{Excno::cell_und, "unexpected special cell"};
}
}
CellSlice cs(std::move(loaded_cell));
DCHECK(cs.size() == Cell::hash_bits + 8);
cell = st->load_library(cs.data_bits() + 8);
if (cell.is_null()) {
if (quiet) {
stack.push_bool(false);
return 0;
} else {
throw VmError{Excno::cell_und, "failed to load library cell"};
}
}
}
stack.push_cell(cell);
if (quiet) {
stack.push_bool(true);
Expand Down
5 changes: 5 additions & 0 deletions crypto/vm/cells/CellSlice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1056,6 +1056,7 @@ std::ostream& operator<<(std::ostream& os, Ref<CellSlice> cs_ref) {
// If can_be_special is not null, then it is allowed to load special cell
// Flag whether loaded cell is actually special will be stored into can_be_special
VirtualCell::LoadedCell load_cell_slice_impl(Ref<Cell> cell, bool* can_be_special) {
bool library_loaded = false;
while (true) {
auto* vm_state_interface = VmStateInterface::get();
if (vm_state_interface) {
Expand All @@ -1076,6 +1077,10 @@ VirtualCell::LoadedCell load_cell_slice_impl(Ref<Cell> cell, bool* can_be_specia
*can_be_special = loaded_cell.data_cell->is_special();
} else if (loaded_cell.data_cell->is_special()) {
if (loaded_cell.data_cell->special_type() == DataCell::SpecialType::Library) {
if (library_loaded) {
throw VmError{Excno::cell_und, "failed to load library cell: recursive library cells are not allowed"};
}
library_loaded = true;
if (vm_state_interface) {
CellSlice cs(std::move(loaded_cell));
DCHECK(cs.size() == Cell::hash_bits + 8);
Expand Down
4 changes: 4 additions & 0 deletions crypto/vm/tonops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ int exec_set_gas_generic(VmState* st, long long new_gas_limit) {
throw VmNoGas{};
}
st->change_gas_limit(new_gas_limit);
if (st->get_stop_on_accept_message()) {
VM_LOG(st) << "External message is accepted, stopping TVM";
return st->jump(td::Ref<QuitCont>{true, 0});
}
return 0;
}

Expand Down
7 changes: 7 additions & 0 deletions crypto/vm/vm.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ class VmState final : public VmStateInterface {
td::HashSet<CellHash> loaded_cells;
int stack_trace{0}, debug_off{0};
bool chksig_always_succeed{false};
bool stop_on_accept_message{false};
td::optional<td::Bits256> missing_library;
td::uint16 max_data_depth = 512; // Default value
int global_version{0};
Expand Down Expand Up @@ -381,6 +382,12 @@ class VmState final : public VmStateInterface {
bool get_chksig_always_succeed() const {
return chksig_always_succeed;
}
void set_stop_on_accept_message(bool flag) {
stop_on_accept_message = flag;
}
bool get_stop_on_accept_message() const {
return stop_on_accept_message;
}
Ref<OrdCont> ref_to_cont(Ref<Cell> cell) const {
return td::make_ref<OrdCont>(load_cell_slice_ref(std::move(cell)), get_cp());
}
Expand Down
1 change: 1 addition & 0 deletions validator/impl/external-message.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ td::Status ExtMessageQ::run_message_on_account(ton::WorkchainId wc,
}
compute_phase_cfg_.libraries = std::make_unique<vm::Dictionary>(config->get_libraries_root(), 256);
compute_phase_cfg_.with_vm_log = true;
compute_phase_cfg_.stop_on_accept_message = true;

auto res = Collator::impl_create_ordinary_transaction(msg_root, acc, utime, lt,
&storage_phase_cfg_, &compute_phase_cfg_,
Expand Down

0 comments on commit 42d4c05

Please sign in to comment.