Skip to content

Fix unchecked map access in xnnpack#18804

Merged
lucylq merged 1 commit intomainfrom
security36
Apr 10, 2026
Merged

Fix unchecked map access in xnnpack#18804
lucylq merged 1 commit intomainfrom
security36

Conversation

@lucylq
Copy link
Copy Markdown
Contributor

@lucylq lucylq commented Apr 10, 2026

Introduce remapId function that checks error instead of std::unordered_map::at(), which throws std::out_of_range in noexcept functions causing std::terminate(). Applied across all ~30 node-definition functions in XNNCompiler.

Authored-with: Claude

@pytorch-bot
Copy link
Copy Markdown

pytorch-bot Bot commented Apr 10, 2026

🔗 Helpful Links

🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/18804

Note: Links to docs will display an error until the docs builds have been completed.

❗ 1 Active SEVs

There are 1 currently active SEVs. If your PR is affected, please view them below:

❌ 2 New Failures, 4 Cancelled Jobs, 2 Unrelated Failures

As of commit ff93cd1 with merge base 21d9c64 (image):

NEW FAILURES - The following jobs have failed:

CANCELLED JOBS - The following jobs were cancelled. Please retry:

BROKEN TRUNK - The following jobs failed but were present on the merge base:

👉 Rebase onto the `viable/strict` branch to avoid these failures

This comment was automatically generated by Dr. CI and updates every 15 minutes.

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Apr 10, 2026
@github-actions
Copy link
Copy Markdown

This PR needs a release notes: label

If your change should be included in the release notes (i.e. would users of this library care about this change?), please use a label starting with release notes:. This helps us keep track and include your important work in the next release notes.

To add a label, you can comment to pytorchbot, for example
@pytorchbot label "release notes: none"

For more information, see
https://github.com/pytorch/pytorch/wiki/PyTorch-AutoLabel-Bot#why-categorize-for-release-notes-and-how-does-it-work.


// Safe lookup in remapped_ids that returns an error instead of throwing
// from std::unordered_map::at() in noexcept functions.
inline Result<uint32_t> remapId(
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use remapId + ET_UNWRAP because a macro could potentially have larger binary size bloat.

@lucylq lucylq marked this pull request as ready for review April 10, 2026 17:28
@lucylq lucylq requested a review from digantdesai as a code owner April 10, 2026 17:28
Copilot AI review requested due to automatic review settings April 10, 2026 17:28
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens XNNPACK runtime compilation by replacing unchecked std::unordered_map::at() accesses (which can throw inside noexcept node-definition functions and trigger std::terminate()) with a safe remapId() helper that returns Result<uint32_t> and propagates an Error instead.

Changes:

  • Add remapId() helper to safely look up remapped tensor/value IDs without exceptions.
  • Update node-definition helpers to use ET_UNWRAP(remapId(...)) instead of remapped_ids.at(...) when defining XNNPACK operators.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +610 to +613
uint32_t key) {
auto it = map.find(key);
if (it == map.end()) {
ET_LOG(Error, "Remapped id not found for key %u", key);
Comment on lines +695 to +697
auto cvt_input_id = ET_UNWRAP(remapId(remapped_ids, graph_node->input_id()));
auto cvt_output_id = ET_UNWRAP(remapId(remapped_ids, graph_node->output_id()));

@JacobSzwejbka
Copy link
Copy Markdown
Contributor

@claude review this PR

@claude
Copy link
Copy Markdown

claude Bot commented Apr 10, 2026

Claude finished @JacobSzwejbka's task in 2m 42s —— View job


PR Review: Fix unchecked map access in XNNPACK compiler

  • Read the changed file and understand context
  • Review the diff
  • Check CI failures for relevance
  • Post review feedback

Summary: This PR replaces all std::unordered_map::at() calls with a safe remapId() helper that returns Result<uint32_t>, preventing std::terminate() from uncaught std::out_of_range exceptions in noexcept functions. The change is applied consistently across ~30 node-definition functions.

Correctness

The core approach is sound. ET_UNWRAP uses a GCC statement expression with a plain return et_result__.error() on failure — no exceptions are thrown — so it is safe in noexcept contexts. The DefineNodeFunc type alias (line 62) returns Error, matching ET_UNWRAP's error propagation. All call sites correctly unwrap remapId results before passing them to xnn_define_* functions.

All ~74 ET_UNWRAP(remapId(...)) call sites follow the same pattern: unwrap into a local variable, then pass it to the XNNPACK API. The unary/binary macro-generated functions (_DEFINE_UNARY_NODE_*, _DEFINE_BINARY_NODE_*) pass raw IDs through to defineGenericUnaryNode / defineGenericBinaryNode, where the remapId check happens centrally. This is a correct and clean design — the generic helpers are the single point of validation.

No remaining .at() calls exist in the file.

Issues

1. Commit message is stale — The commit says "replace remapped_ids.at() with safe REMAP_ID macro" but the implementation uses a remapId() function (not a macro). The PR title/description is correct. Minor but worth fixing before merge.

2. Lint failure (clang-format) — needs fix — CI reports formatting violations at several locations. The issues are minor whitespace/line-break differences. Running lintrunner -a should resolve them. Specific locations from the log:

  • Line 695-698: cvt_output_id assignment and xnn_define_convert call formatting
  • Line 1201-1202: amp_out_val/amp_out_idx line breaks
  • Line 1243-1244: xnn_define_exp call formatting
  • Line 1303: xnn_define_prelu argument wrapping
  • Line 1598-1603: xnn_define_unary argument formatting

Fix formatting →

3. Error message lacks node context — (echoing Copilot's review comment) The remapId error message only logs the missing key:

ET_LOG(Error, "Remapped id not found for key %u", key);

When this fails, the caller is deep in one of ~30 define*Node functions. Without a node type or debug handle, diagnosing which operator hit the bad ID requires a debugger. Consider using the 2-arg form of ET_UNWRAP at the call sites for key nodes:

auto fc_input1 = ET_UNWRAP(
    remapId(remapped_ids, graph_node->input1_id()),
    "input1_id remap failed for node %u", node->debug_handle());

This is a quality-of-life improvement and not a blocker.

Unrelated CI failures

  • Cadence (test_replace_transposed_conv_with_linear_0): unrelated to XNNPACK changes.
  • Samsung models (test_w2l_fp16): unrelated to XNNPACK changes.
  • Windows failures: broken trunk (present on merge base).

Overall

The security fix is correct and well-structured. The remapId + ET_UNWRAP approach is the right pattern for ExecuTorch — it matches idiomatic error handling throughout the codebase, avoids exceptions in noexcept functions, and centralizes the safety check in one place.

The only blocking issue is the clang-format lint failure, which should be a straightforward fix with lintrunner -a.


Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens the XNNPACK runtime compiler against unchecked tensor-id remapping lookups that could previously throw std::out_of_range inside noexcept node-definition functions (leading to std::terminate()), by converting those lookups into Result-based error propagation.

Changes:

  • Added a remapId() helper that safely looks up remapped tensor IDs and returns an Error on missing keys rather than throwing.
  • Replaced remapped_ids.at(...) usages across node-definition helpers with ET_UNWRAP(remapId(...)) to propagate errors cleanly.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +606 to +615
// Safe lookup in remapped_ids that returns an error instead of throwing
// from std::unordered_map::at() in noexcept functions.
inline Result<uint32_t> remapId(
const std::unordered_map<uint32_t, uint32_t>& map,
uint32_t key) {
auto it = map.find(key);
if (it == map.end()) {
ET_LOG(Error, "Remapped id not found for key %u", key);
return Error::Internal;
}
…acro

Introduce REMAP_ID macro that uses find() + ET_CHECK_OR_RETURN_ERROR
instead of std::unordered_map::at(), which throws std::out_of_range in
noexcept functions causing std::terminate(). Applied across all ~30
node-definition functions in XNNCompiler.

Authored-with: Claude
@lucylq
Copy link
Copy Markdown
Contributor Author

lucylq commented Apr 10, 2026

I think the key is enough to correlate with the flatbuffer, and don't need the additional context / can get noisy.

Copy link
Copy Markdown
Member

@GregoryComer GregoryComer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me. One note - ET_UNWRAP relies on Clang/GCC-specific extensions and won't build with MSVC. I don't know what guarantees we want to make for MSVC, in general, so it might be fine. CC @JacobSzwejbka

@lucylq lucylq merged commit 273aee9 into main Apr 10, 2026
159 of 167 checks passed
@lucylq lucylq deleted the security36 branch April 10, 2026 21:30
lucylq added a commit that referenced this pull request Apr 10, 2026
lucylq added a commit that referenced this pull request Apr 10, 2026
Reverts #18804, which is breaking windows tests
jpiat pushed a commit to jpiat/executorch that referenced this pull request Apr 14, 2026
Introduce remapId function that checks error instead of
std::unordered_map::at(), which throws std::out_of_range in noexcept
functions causing std::terminate(). Applied across all ~30
node-definition functions in XNNCompiler.

Authored-with: Claude

Co-authored-by: Github Executorch <github_executorch@arm.com>
jpiat pushed a commit to jpiat/executorch that referenced this pull request Apr 14, 2026
lucylq added a commit that referenced this pull request Apr 21, 2026
Introduce remapId function that checks error instead of
std::unordered_map::at(), which throws std::out_of_range in noexcept
functions causing std::terminate(). Applied across all ~30
node-definition functions in XNNCompiler.

retake #18804, for windows
compatibility

Co-authored-by: Github Executorch <github_executorch@arm.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants