Skip to content
Draft
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
22 changes: 22 additions & 0 deletions runtime/executor/method.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,15 @@ namespace ET_RUNTIME_NAMESPACE {

using internal::PlatformMemoryAllocator;

// Maximum number of instructions that Method::execute() will run before
// returning an error. Prevents infinite loops caused by malformed programs
// (e.g., JumpFalseCall instructions whose destination_instruction points to
// themselves). Override at compile time via -DET_MAX_INSTRUCTIONS=<value>.
#ifndef ET_MAX_INSTRUCTIONS
#define ET_MAX_INSTRUCTIONS 10000000
#endif
static constexpr size_t kMaxInstructions = ET_MAX_INSTRUCTIONS;

/**
* Runtime state for a backend delegate.
*/
Expand Down Expand Up @@ -1644,6 +1653,7 @@ Error Method::execute() {

// Chains are executed sequentially today, but future async designs may
// branch and run many in parallel or out of order.
size_t instruction_count = 0;
for (step_state_.chain_idx = 0; step_state_.chain_idx < n_chains_;
++step_state_.chain_idx) {
Chain& chain = chains_[step_state_.chain_idx];
Expand All @@ -1657,6 +1667,18 @@ Error Method::execute() {
// Loop over instructions
step_state_.instr_idx = 0;
while (step_state_.instr_idx < chain.s_chain_->instructions()->size()) {
if (instruction_count >= kMaxInstructions) {
ET_LOG(
Error,
"Instruction execution limit (%" ET_PRIsize_t
") exceeded in chain %" ET_PRIsize_t
". Possible infinite loop detected.",
kMaxInstructions,
step_state_.chain_idx);
step_state_ = StepState{0, 0};
return Error::InvalidState;
}
++instruction_count;
EXECUTORCH_PROFILE_INSTRUCTION_SCOPE(
static_cast<int32_t>(step_state_.chain_idx),
static_cast<uint32_t>(step_state_.instr_idx));
Expand Down
Loading