External audit triage: all 18 findings addressed#450
External audit triage: all 18 findings addressed#450thedavidmeister wants to merge 15 commits intomainfrom
Conversation
RHS offset 62 causes pushOpToSource to write into the LHS counter byte at state + 0x5F instead of a per-word ops counter. Lower the constant from 0x3f to 0x3e so highwater() rejects offset 62 before it can collide. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
endLine() adds lineLHSItems to totalRHSTopLevel without checking the limit when a line has only LHS items and no RHS. Add the same >= MAX_STACK_RHS_OFFSET check that highwater() uses so large input declarations revert with ParseStackOverflow instead of corrupting parser state. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
LibOpExtern.integrity() passed through whatever externIntegrity() returned without checking it matched the operand-encoded IO counts. A malicious extern could lie consistently at parse and integrity time. Now assert the returned inputs and outputs match the operand, reverting with ExternIntegrityInputsMismatch or ExternIntegrityOutputsMismatch. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
L02: outputs was extracted via unmasked right shift (>> 0x14), reading bits above the 4-bit field. Add & 0x0F mask to both integrity() and run() for consistency with other opcodes. L03: integrity() returned sourceInputs from the bytecode without comparing against the operand-encoded inputs. Add an explicit equality assertion that reverts with CallInputsMismatchSource on mismatch, making the opcode self-validating. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Opcode integrity() functions report stack IO to integrityCheck2, which is the single validation authority. Opcode run() functions trust that integrity has already validated the bytecode and do not duplicate checks — runtime gas efficiency depends on this separation. Documented in CLAUDE.md, README.md, and integrityCheck2 NatSpec. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
I01: Add comment noting MalformedHexLiteral revert is a defensive unreachable fallback in LibParseLiteralHex. I04: Add OutOfBoundsConstantRead check in LibOpExtern.integrity() matching the LibOpConstant pattern. I05: Replace implicit mload(state) with explicit state.stackBottoms field access in LibOpStack.run(). I08: Move checkParseMemoryOverflow() inside LibParse.parse() after buildBytecode/subParseWords so it enforces the 16-bit pointer limit internally. Remove redundant modifier from RainterpreterParser.unsafeParse. Rebuild pointers for the parser bytecode change. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Update interface submodule to latest main (includes float dep with identity fuzz test). All 18 external audit findings now triaged. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughBytecode integrity validation is centralized in Changes
Sequence Diagram(s)mermaid Estimated Code Review Effort🎯 4 (Complex) | ⏱️ ~50 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/lib/parse/LibParseState.sol (1)
81-87: Clarify that this is an exclusive bound.
MAX_STACK_RHS_OFFSETnow stores the first invalid offset (0x3e), not the highest valid one. Rewording the lead sentence here would make the boundary harder to misread next time.✏️ Suggested wording
-/// `@dev` Maximum RHS offset value. The RHS offset is stored as a single +/// `@dev` Exclusive upper bound for the RHS offset. The RHS offset is stored as a single🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/lib/parse/LibParseState.sol` around lines 81 - 87, The comment for MAX_STACK_RHS_OFFSET is misleading because the constant holds the first invalid offset (0x3e) rather than the maximum valid offset; update the docstring for MAX_STACK_RHS_OFFSET to explicitly state it is an exclusive upper bound (first invalid offset = 0x3e) and that the highest valid RHS offset is 0x3d (61), and preserve the existing explanation about why offset 62 would overflow into the LHS counter byte (referencing topLevel0, topLevel1, and pushOpToSource) so readers don’t misinterpret the constant's meaning.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@src/lib/parse/LibParseState.sol`:
- Around line 81-87: The comment for MAX_STACK_RHS_OFFSET is misleading because
the constant holds the first invalid offset (0x3e) rather than the maximum valid
offset; update the docstring for MAX_STACK_RHS_OFFSET to explicitly state it is
an exclusive upper bound (first invalid offset = 0x3e) and that the highest
valid RHS offset is 0x3d (61), and preserve the existing explanation about why
offset 62 would overflow into the LHS counter byte (referencing topLevel0,
topLevel1, and pushOpToSource) so readers don’t misinterpret the constant's
meaning.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: a6cc9f15-4fec-476b-b98e-6d40933a2e32
⛔ Files ignored due to path filters (8)
CLAUDE.mdis excluded by!CLAUDE.mdaudit/2026-03-23-01/triage.mdis excluded by!audit/**flake.lockis excluded by!**/*.lockfoundry.lockis excluded by!**/*.locksrc/generated/Rainlang.pointers.solis excluded by!**/generated/**src/generated/Rainterpreter.pointers.solis excluded by!**/generated/**src/generated/RainterpreterExpressionDeployer.pointers.solis excluded by!**/generated/**src/generated/RainterpreterParser.pointers.solis excluded by!**/generated/**
📒 Files selected for processing (18)
README.mdlib/rain.interpreter.interfacesrc/concrete/RainterpreterParser.solsrc/error/ErrExtern.solsrc/error/ErrIntegrity.solsrc/lib/integrity/LibIntegrityCheck.solsrc/lib/op/00/LibOpExtern.solsrc/lib/op/00/LibOpStack.solsrc/lib/op/call/LibOpCall.solsrc/lib/parse/LibParse.solsrc/lib/parse/LibParseState.solsrc/lib/parse/literal/LibParseLiteralHex.soltest/src/lib/op/00/LibOpExtern.t.soltest/src/lib/op/call/LibOpCall.t.soltest/src/lib/parse/LibParseState.endLine.unboundedLHS.t.soltest/src/lib/parse/LibParseState.highwater.t.soltest/src/lib/parse/LibParseState.highwaterOverflow.t.soltest/src/lib/parse/LibParseState.pushOpToSource.LHSCorruption.t.sol
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This reverts commit 456ee48.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The audit branch added a runtime inputs check in LibOpCall.run() that reverts with CallInputsMismatchSource before the integrity-level BadOpInputsLength check fires. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
Triages all 18 findings from the external audit report (Report_rain.interpreter_2.0_mar_2026.pdf).
Security fixes (H01, M01-M06, L01-L03)
Informational fixes (I01-I08)
Other
Test plan
🤖 Generated with Claude Code
Summary by CodeRabbit
Bug Fixes
Documentation
Tests