Skip to content

Fix wrong iterator in InterpDropKeep ref tracking#2692

Open
sumleo wants to merge 1 commit intoWebAssembly:mainfrom
sumleo:fix/interp-dropkeep-iterator
Open

Fix wrong iterator in InterpDropKeep ref tracking#2692
sumleo wants to merge 1 commit intoWebAssembly:mainfrom
sumleo:fix/interp-dropkeep-iterator

Conversation

@sumleo
Copy link
Contributor

@sumleo sumleo commented Feb 12, 2026

Summary

  • In the InterpDropKeep handler in interp.cc, the second loop ("find dropped refs") checked *iter instead of *drop_iter in its break condition, causing incorrect erasure of ref-tracking entries in the refs_ vector.
  • This could lead to reference-typed values losing their GC root tracking while still alive on the value stack.
  • Add a regression test that exercises drop=2/keep=1 with three externref values on the stack.

Details

The InterpDropKeep handler has two loops over refs_ (reverse iterators):

  1. First loop (iter): shifts kept refs down by drop positions.
  2. Second loop (drop_iter): finds dropped refs to erase.

The bug is in the second loop:

auto drop_iter = iter;
for (; drop_iter != refs_.rend(); ++drop_iter) {
  if (*iter < values_.size() - keep - drop) {  // BUG: should be *drop_iter
    break;
  }
}

Since iter is not advanced in this loop, the break condition is evaluated against a stale value on every iteration. This causes the loop to either break too early (erasing too few entries) or never break (erasing too many entries), depending on the stale *iter value relative to the boundary.

Fix: Change *iter to *drop_iter.

Test plan

  • New test InterpTest.DropKeepRefTracking creates a wasm module with 3 externref params, a block that pushes all three to the stack, and a br that triggers drop=2/keep=1
  • All existing unit tests pass (128 tests)

In the InterpDropKeep handler, the second loop ("find dropped refs")
checked *iter instead of *drop_iter in its break condition.  Since
iter was not advanced in this loop, the condition was evaluated against
a stale value on every iteration, causing incorrect erasure of ref
tracking entries in the refs_ vector.

This could lead to reference-typed values losing their tracking in the
GC root set while still alive on the value stack, potentially allowing
premature collection during garbage collection.

Add a regression test that exercises drop=2/keep=1 with three
externref values on the stack.
@sumleo sumleo force-pushed the fix/interp-dropkeep-iterator branch from 548bcdb to 42fd0f4 Compare February 12, 2026 08:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant