From f9e7d86c662ae23fe34a96af4538d10d145cd8a2 Mon Sep 17 00:00:00 2001 From: Github Executorch Date: Wed, 4 Mar 2026 17:13:55 -0800 Subject: [PATCH] Add bounds validation for FreeCall value_index in Method The FreeCall instruction handler directly indexes into values_ without bounds checking, enabling OOB memory access via malicious PTE files. This contrasts with JumpFalseCall which validates its index at init time, and MoveCall which uses bounds-checked accessors at execution time. Add init-time validation for FreeCall matching the JumpFalseCall pattern, and switch execution-time access to use the bounds-checked mutable_value() accessor for defense in depth. Addresses TOB-EXECUTORCH-15. This PR was authored with the assistance of Claude. --- runtime/executor/method.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/runtime/executor/method.cpp b/runtime/executor/method.cpp index 474afc446d2..66edce2a20f 100644 --- a/runtime/executor/method.cpp +++ b/runtime/executor/method.cpp @@ -1060,6 +1060,19 @@ Error Method::init( n_value_); chain_instruction_arg_lists[instr_idx] = InstructionArgs(); } break; + case executorch_flatbuffer::InstructionArguments::FreeCall: { + auto index = + static_cast( + instr_args) + ->value_index(); + ET_CHECK_OR_RETURN_ERROR( + index >= 0 && static_cast(index) < n_value_, + InvalidProgram, + "Index %zd negative or >= %" ET_PRIsize_t, + static_cast(index), + n_value_); + chain_instruction_arg_lists[instr_idx] = InstructionArgs(); + } break; default: { chain_instruction_arg_lists[instr_idx] = InstructionArgs(); } break; @@ -1501,7 +1514,7 @@ Error Method::execute_instruction() { // We know that instr_args_as_FreeCall is non-null because it was checked // at init time. auto free_call = instruction->instr_args_as_FreeCall(); - auto t = values_[free_call->value_index()].toTensor(); + auto t = mutable_value(free_call->value_index()).toTensor(); internal::reset_data_ptr(t); } break; default: