Skip to content

fix: prevent initializer name collision in rewrite rule registration#2946

Open
OYCN wants to merge 1 commit into
microsoft:mainfrom
OYCN:fix/rewrite-initializer-name-clobbering
Open

fix: prevent initializer name collision in rewrite rule registration#2946
OYCN wants to merge 1 commit into
microsoft:mainfrom
OYCN:fix/rewrite-initializer-name-clobbering

Conversation

@OYCN

@OYCN OYCN commented Jun 22, 2026

Copy link
Copy Markdown

Summary

#2945

Fix a bug where multiple rewrite rule matches producing initializers with the same name would silently clobber each other, resulting in a dangling ir.Value reference and a toposort validation failure on serialization.

Problem

When two Reshape→Reshape chains share the same shape initializer (e.g. containing -1), the ReshapeReshape rule fires twice, each time calling op.initializer(ir.Tensor(..., name=shape.name)). Both produce an initializer with the same name but different resolved values.

The registration logic in _rewrite_rule.py had two independent for-loops:

# Loop 1: check for duplicates (dead code — `continue` only skips this loop)
for initializer in delta.new_initializers:
    if initializer.name in initializers:
        continue

# Loop 2: unconditionally overwrite
for initializer in delta.new_initializers:
    initializers[initializer.name] = initializer

The second loop always overwrote the dict entry, so the first registered Value lost its dict reference. NameFixPass would then rename it to ensure uniqueness, but never re-registered it as an initializer — leaving it as a dangling reference that fails onnx.checker.

Fix

Merge into a single loop. On name conflict with a different Value object, auto-generate a unique suffix (_1, _2, ...) and register under the new name. Since node inputs hold object references (not name strings), the rename propagates correctly on serialization.

Test

Added test_reshape_reshape_shared_shape_no_clobbering covering the shared-shape scenario. Asserts that all shape Values are registered initializers and the serialized model passes onnx.checker.check_model(full_check=True).

Related

Also filed a separate issue/PR in onnx-ir for NameFixPass not registering renamed Values as initializers — that's an independent bug exposed by the same scenario.

When multiple rewrite matches produce initializers with the same name,
the second registration would silently overwrite the first in the
graph.initializers dict. The original Value became an unregistered
dangling reference, causing toposort validation failure on serialization.

The root cause was two independent for-loops: the first checked for
duplicates but its `continue` only affected itself (dead code), while
the second unconditionally overwrote all entries.

Fix: merge into a single loop that detects name conflicts and
auto-generates a unique suffix (_1, _2, ...) before registering.

Signed-off-by: opluss <opluss@qq.com>
@OYCN

OYCN commented Jun 22, 2026

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

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

Labels

None yet

Projects

Development

Successfully merging this pull request may close these issues.

1 participant