Skip to content

executor_runner segfaults in portable kernels when a .pte tensor has neither a data buffer nor a memory plan (null data pointer)聽#23955

Open

Description

@professor-moody

馃悰 Describe the bug

A .pte can declare a tensor with data_buffer_idx == 0 and no allocation_info. getTensorDataPtr (runtime/executor/tensor_parser_exec_aten.cpp:289-291 at main 897d28fe) accepts this case as "pointer received at runtime" and returns nullptr. If that tensor is not a plan input, nothing requires a data pointer to be supplied before Method::execute(): execute checks only input_set_ (method.cpp:1792-1799). The portable kernels then load or store through the null pointer (kernels/portable/cpu/util/dtype_util.h:20-27, elementwise_util.h:191), because Tensor::const_data_ptr / mutable_data_ptr (runtime/core/portable_type/tensor.h:135-153) do not check for null.

Reproduced on 2026-10-18 at main 897d28fe3094f27898115ebd65fecafdef5970cb (Linux x86_64, clang 21.1.8) with the shipped examples/portable/executor_runner --model_path <file>.pte. Seven fuzzer-generated .pte files (704 to 764 bytes each; all seven fault inside add_out) were run through three builds:

                     ASan+UBSan -O1   Release -O3 -DNDEBUG   Release + logging
7 crafted .pte       exit 1           exit 139 (SIGSEGV)     exit 139
upstream add model   exit 0           exit 0                 exit 0

UBSan reports, for example:

kernels/portable/cpu/util/elementwise_util.h:191:11: runtime error: store to null pointer of type 'float'
kernels/portable/cpu/util/dtype_util.h:21:26: runtime error: load of null pointer of type 'const float'
  ... torch::executor::native::add_out(...)
  ... executorch::runtime::Method::execute_instruction() runtime/executor/method.cpp:1557:7
  ... executorch::runtime::Method::execute() runtime/executor/method.cpp:1844:21
  ... main examples/portable/executor_runner/executor_runner.cpp:856:28

I found #19269, which proposed a null check in the six Tensor data accessors to cover a large class of internal fuzzer crashes. It was closed without merging, and the accessors at 897d28fe still have no check. This report adds a file-only path to the same state: the .pte alone produces the null-data tensor, through the stock runner's default flow. Possible fixes are to reject such a tensor at load unless it is a plan input or output, to require output pointers to be set before execute(), or to add the accessor check from #19269. I am happy to send a PR for whichever you prefer.

Two smaller null dereferences on the same malformed-input path, also reproduced at 897d28fe with the shipped runner:

  • Method::execute_instruction formats op->overload()->c_str() in the "KernelCall failed" ET_LOG (method.cpp:1565-1573) without the has_overload guard that populate_operator_name uses at load time (:756-768). A .pte whose operator has no overload string, plus any kernel check failure, segfaults in an -O3 -DNDEBUG runner built with EXECUTORCH_ENABLE_LOGGING=ON (exit 139; ASan: SEGV at address 0x4 in strlen via vsnprintf from method.cpp:1565). The same .pte without the kernel failure runs normally, and a kernel failure with the overload present exits cleanly with the logged error.
  • get_named_data (extension/flat_tensor/flat_tensor_data_map.cpp:66) and FlatTensorDataMap::get_key (:263) call key()->size() / key()->c_str() without a null check. A .ptd with a NamedData entry that omits key segfaults at address 0 in executor_runner --model_path ... --data_path ... (ASan: flat_tensor_data_map.cpp:66:50: runtime error: member call on null pointer of type 'flatbuffers::Vector<char>').

I have a small patch for these two, returning InvalidExternalData for a missing key and using "" for a missing overload. I can attach the crafted files, the controls, and the generator for the last two on request. Every run above recorded the SHA-256 of the binary and the input before and after.

Versions

main 897d28fe3094f27898115ebd65fecafdef5970cb (2026-10-18), built from source; Fedora 43 x86_64, clang 21.1.8, cmake 3.31.11. Release builds use -DCMAKE_BUILD_TYPE=Release (-O3 -DNDEBUG). Release v1.5.1 has the same source at these sites but was not run. (The template's collect_env.py output is not applicable to a C++ source build; paste it if the maintainers ask.)

Disclosure

AI tooling was used and assisted in the discovery and authoring of this issue.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions