mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
Disallow recursive library cells (#868)
* Disallow recursive library cells * Stop emulation of external messages on accept --------- Co-authored-by: SpyCheese <mikle98@yandex.ru>
This commit is contained in:
parent
128a85bee5
commit
42d4c051ef
7 changed files with 50 additions and 0 deletions
|
@ -1559,6 +1559,7 @@ bool Transaction::prepare_compute_phase(const ComputePhaseConfig& cfg) {
|
||||||
vm.set_global_version(cfg.global_version);
|
vm.set_global_version(cfg.global_version);
|
||||||
vm.set_c7(prepare_vm_c7(cfg)); // tuple with SmartContractInfo
|
vm.set_c7(prepare_vm_c7(cfg)); // tuple with SmartContractInfo
|
||||||
vm.set_chksig_always_succeed(cfg.ignore_chksig);
|
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
|
// vm.incr_stack_trace(1); // enable stack dump after each step
|
||||||
|
|
||||||
LOG(DEBUG) << "starting VM";
|
LOG(DEBUG) << "starting VM";
|
||||||
|
|
|
@ -120,6 +120,7 @@ struct ComputePhaseConfig {
|
||||||
std::unique_ptr<vm::Dictionary> suspended_addresses;
|
std::unique_ptr<vm::Dictionary> suspended_addresses;
|
||||||
SizeLimitsConfig size_limits;
|
SizeLimitsConfig size_limits;
|
||||||
int vm_log_verbosity = 0;
|
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) {
|
ComputePhaseConfig() : gas_price(0), gas_limit(0), special_gas_limit(0), gas_credit(0) {
|
||||||
compute_threshold();
|
compute_threshold();
|
||||||
|
|
|
@ -892,6 +892,37 @@ int exec_load_special_cell(VmState* st, bool quiet) {
|
||||||
Stack& stack = st->get_stack();
|
Stack& stack = st->get_stack();
|
||||||
VM_LOG(st) << "execute XLOAD" << (quiet ? "Q" : "");
|
VM_LOG(st) << "execute XLOAD" << (quiet ? "Q" : "");
|
||||||
auto cell = stack.pop_cell();
|
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);
|
stack.push_cell(cell);
|
||||||
if (quiet) {
|
if (quiet) {
|
||||||
stack.push_bool(true);
|
stack.push_bool(true);
|
||||||
|
|
|
@ -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
|
// 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
|
// 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) {
|
VirtualCell::LoadedCell load_cell_slice_impl(Ref<Cell> cell, bool* can_be_special) {
|
||||||
|
bool library_loaded = false;
|
||||||
while (true) {
|
while (true) {
|
||||||
auto* vm_state_interface = VmStateInterface::get();
|
auto* vm_state_interface = VmStateInterface::get();
|
||||||
if (vm_state_interface) {
|
if (vm_state_interface) {
|
||||||
|
@ -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();
|
*can_be_special = loaded_cell.data_cell->is_special();
|
||||||
} else if (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 (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) {
|
if (vm_state_interface) {
|
||||||
CellSlice cs(std::move(loaded_cell));
|
CellSlice cs(std::move(loaded_cell));
|
||||||
DCHECK(cs.size() == Cell::hash_bits + 8);
|
DCHECK(cs.size() == Cell::hash_bits + 8);
|
||||||
|
|
|
@ -67,6 +67,10 @@ int exec_set_gas_generic(VmState* st, long long new_gas_limit) {
|
||||||
throw VmNoGas{};
|
throw VmNoGas{};
|
||||||
}
|
}
|
||||||
st->change_gas_limit(new_gas_limit);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -98,6 +98,7 @@ class VmState final : public VmStateInterface {
|
||||||
td::HashSet<CellHash> loaded_cells;
|
td::HashSet<CellHash> loaded_cells;
|
||||||
int stack_trace{0}, debug_off{0};
|
int stack_trace{0}, debug_off{0};
|
||||||
bool chksig_always_succeed{false};
|
bool chksig_always_succeed{false};
|
||||||
|
bool stop_on_accept_message{false};
|
||||||
td::optional<td::Bits256> missing_library;
|
td::optional<td::Bits256> missing_library;
|
||||||
td::uint16 max_data_depth = 512; // Default value
|
td::uint16 max_data_depth = 512; // Default value
|
||||||
int global_version{0};
|
int global_version{0};
|
||||||
|
@ -381,6 +382,12 @@ class VmState final : public VmStateInterface {
|
||||||
bool get_chksig_always_succeed() const {
|
bool get_chksig_always_succeed() const {
|
||||||
return chksig_always_succeed;
|
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 {
|
Ref<OrdCont> ref_to_cont(Ref<Cell> cell) const {
|
||||||
return td::make_ref<OrdCont>(load_cell_slice_ref(std::move(cell)), get_cp());
|
return td::make_ref<OrdCont>(load_cell_slice_ref(std::move(cell)), get_cp());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_.libraries = std::make_unique<vm::Dictionary>(config->get_libraries_root(), 256);
|
||||||
compute_phase_cfg_.with_vm_log = true;
|
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,
|
auto res = Collator::impl_create_ordinary_transaction(msg_root, acc, utime, lt,
|
||||||
&storage_phase_cfg_, &compute_phase_cfg_,
|
&storage_phase_cfg_, &compute_phase_cfg_,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue