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_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";
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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};
|
||||
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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_,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue