Yul optimizer: popScope omits variableChanged() on KnowledgeBase — sibling of PR #17116 (and 865543a6)
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 55/100
Research direction
Start in libyul/optimiser/DataFlowAnalyzer.cpp, where popScope() erases m_state.value and m_state.sortedReferences without calling m_knowledgeBase.variableChanged(). Compare it with clearValues(), which already makes that call, and check libyul/optimiser/Suite.cpp to confirm the reachability claim. Done means the invalidation is consistent across the mutators and the existing Yul optimizer tests still pass.
Written by the indexing model from the issue text.
Description
Summary
PR #17116 (merged 2026-10-14) + its parent commit 865543a6 fixed YulOptimizerKnowledgeBaseMissesStaleBase by versioning KnowledgeBase's offset cache (keyed by (name, version) instead of just name) and adding m_knowledgeBase.variableChanged(name) calls to DataFlowAnalyzer::clearValues().
The sibling path DataFlowAnalyzer::popScope() (currently libyul/optimiser/DataFlowAnalyzer.cpp:290-299) erases m_state.value[name] but does not call variableChanged():
void DataFlowAnalyzer::popScope()
{
for (auto const& name: m_variableScopes.back().variables)
{
m_state.value.erase(name);
m_state.sortedReferences.erase(name);
// ← missing: m_knowledgeBase.variableChanged(name);
}
m_variableScopes.pop_back();
}
grep -rn "m_state\.value\.erase\|m_state\.value\[" libyul/optimiser/DataFlowAnalyzer.cpp returns three erase/assign sites: clearValues() has the variableChanged call added by the fix; popScope() and assignValue() do not. assignValue() is called from handleAssignment() which runs clearValues(_variables) first on non-declarations, so it's covered via that path. popScope() is not covered.
Why it may matter (bounded)
If a later scope reuses the same YulName (which is possible pre-Disambiguator or in non-standard pipeline configurations), KnowledgeBase's m_currentVersions[name] stays at the old value, and explore(name) would return the stale cached offset computed in the earlier scope's lifetime. The yulAssert(cachedOffset->computedFrom == assignedValue) in explore() would catch pointer mismatch in debug; in release where assertions are stripped, same miscompile class as PR #17116.
Reachability caveat (honest)
libyul/optimiser/Suite.cpp:115 runs Disambiguator unconditionally before every user-controllable optimizer step. --yul-optimizations appends to the sequence AFTER Disambiguator and cannot schedule VarNameCleaner (not in stepNameToAbbreviationMap). So from the shipped solc binary, the sibling is not reachable: Disambiguator guarantees unique YulName across the function/block, defusing the trigger.
Reaching this would need a custom libyul consumer that bypasses Disambiguator — not a security scenario for shipped solc. Filing as code-review / defense-in-depth rather than bug.
Secondary observation
Commit 865543a6 is a second parent-fix in the same KnowledgeBase area that also missed popScope(). Two independent parent fixes in the same area closing adjacent but not this spot slightly raise the prior that it's an oversight rather than a design choice.
Suggested fix (one-line defense-in-depth)
void DataFlowAnalyzer::popScope()
{
for (auto const& name: m_variableScopes.back().variables)
{
m_state.value.erase(name);
m_state.sortedReferences.erase(name);
m_knowledgeBase.variableChanged(name); // match clearValues invariant
}
m_variableScopes.pop_back();
}
Tightens the invariant across all m_state.value mutators even though the shipped-binary flow is already safe via Disambiguator.
References
- Fix PR: #17116 (merged 2026-10-14)
- Parent fix commit:
865543a6"Yul Optimizer: Knowledge uses versioned variable names" - Current main reference:
libyul/optimiser/DataFlowAnalyzer.cpp:290-299 - Reachability guard:
libyul/optimiser/Suite.cpp:115(Disambiguatoralways runs)
Reporter: symposia-gi (General Imperative, Symposia). Code-review observation only, defense-in-depth. Not a security report.
- Dominant language
- C++
- Stars
- 25.8k
- Forks
- 6.2k
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 43
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from argotorg/solidity
-
AI tool policy: add AGENTS.mdMay be free again @cameel claimed this 47 days ago, and no pull request is open. Opendocumentation :book:
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
argotorg/solidity#16996 · 2 comments · 1 assignee ·
Maintainers usually reply within 1 day
-
`fitsPrecisionExp` charges the base's bit *length* per multiplication instead of its bit *position*, so valid constant powers such as `2 ** 2049` are rejectedPossibly taken @clonker claimed this 54 days ago. Openbug :bug:
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
argotorg/solidity#16984 · 1 comment · 1 assignee ·
Maintainers usually reply within 1 day
-
`0 ** (-1)` is silently evaluated to `0` in a constant expression instead of being rejected as division by zeroMay be free again @matheusaaguiar claimed this 54 days ago, and no pull request is open. Openbug :bug: low impact
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
argotorg/solidity#16982 · 3 comments · 1 assignee ·
Maintainers usually reply within 1 day
-
AssemblyItem AssemblyItem::toSubAssemblyTag assumes size_t is at least 64bPossibly taken @riba2534 claimed this 67 days ago. Openbug :bug: low impact
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
FileReader: Duplicate search paths cause false ambiguous importsPossibly taken @zjuncal claimed this 2 days ago. Openbug :bug:
Difficulty 2/5 1-3 hours Newbie friendliness 35/100
Maintainers usually reply within 1 day
All issues in argotorg/solidity
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 3 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
KLayout/klayout#2554 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
LaneDibello/Kotor-Patch-Manager#375 ·
Maintainers usually reply within 2 days