-
Notifications
You must be signed in to change notification settings - Fork 955
Add instruction execution limit to prevent infinite loops #18679
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -37,6 +37,20 @@ 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_assert( | ||
| (ET_MAX_INSTRUCTIONS) > 0, | ||
| "ET_MAX_INSTRUCTIONS must be positive. 0 would reject every program on " | ||
| "its first instruction; negative values wrap to SIZE_MAX when assigned " | ||
| "to size_t, silently disabling the infinite-loop guard."); | ||
| static constexpr size_t kMaxInstructions = ET_MAX_INSTRUCTIONS; | ||
|
|
||
| /** | ||
| * Runtime state for a backend delegate. | ||
| */ | ||
|
|
@@ -1661,6 +1675,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]; | ||
|
|
@@ -1674,6 +1689,21 @@ 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 at chain %" ET_PRIsize_t ", instruction %" ET_PRIsize_t | ||
| ". Possible infinite loop detected. If this is a legitimate " | ||
| "large model, raise the limit by rebuilding with " | ||
| "-DET_MAX_INSTRUCTIONS=<value>.", | ||
| kMaxInstructions, | ||
| step_state_.chain_idx, | ||
| step_state_.instr_idx); | ||
| step_state_ = StepState{0, 0}; | ||
| return Error::InvalidProgram; | ||
| } | ||
|
Comment on lines
+1692
to
+1705
|
||
| ++instruction_count; | ||
| EXECUTORCH_PROFILE_INSTRUCTION_SCOPE( | ||
| static_cast<int32_t>(step_state_.chain_idx), | ||
| static_cast<uint32_t>(step_state_.instr_idx)); | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.