-
Notifications
You must be signed in to change notification settings - Fork 2
Add LibInterpreterStateDataContract.bytecodeOf serialized-blob extractor #531
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -311,4 +311,45 @@ contract LibInterpreterStateDataContractTest is Test { | |
| assertEq(lengths[0], stackAllocation0); | ||
| assertEq(lengths[1], stackAllocation1); | ||
| } | ||
|
|
||
| /// `bytecode` returns exactly the body `unsafeDeserialize` references, for | ||
| /// fuzzed constants — the constants-skip in both must agree. | ||
| function testBytecodeMatchesDeserialize(bytes32[] memory constants) external view { | ||
| bytes memory expected = buildTwoSourceBytecode(3, 5); | ||
| bytes memory serialized = serialize(expected, constants); | ||
|
|
||
| bytes memory got = LibInterpreterStateDataContract.bytecodeOf(serialized); | ||
| assertEq(got.length, expected.length); | ||
| assertEq(keccak256(got), keccak256(expected)); | ||
|
|
||
| InterpreterState memory state = iExtern.deserialize( | ||
| serialized, 0, FullyQualifiedNamespace.wrap(0), IInterpreterStoreV3(address(0)), new bytes32[][](0), "" | ||
| ); | ||
| assertEq(keccak256(got), keccak256(state.bytecode)); | ||
| } | ||
|
|
||
| /// `bytecode` round-trips a single-source body behind fuzzed constants. | ||
| function testBytecodeSingleSource(bytes32[] memory constants) external pure { | ||
| bytes memory expected = buildSingleSourceBytecode(1, 2, 0, 1); | ||
| bytes memory serialized = serialize(expected, constants); | ||
| bytes memory got = LibInterpreterStateDataContract.bytecodeOf(serialized); | ||
| assertEq(got.length, expected.length); | ||
| assertEq(keccak256(got), keccak256(expected)); | ||
| } | ||
|
|
||
| /// A blob too short to hold both length words yields empty bytecode. | ||
| function testBytecodeTooShortIsEmpty(bytes memory serialized) external view { | ||
| vm.assume(serialized.length < 0x40); | ||
| assertEq(LibInterpreterStateDataContract.bytecodeOf(serialized).length, 0); | ||
| } | ||
|
|
||
| /// A declared constants length that overruns the blob yields empty bytecode. | ||
| function testBytecodeOverrunConstantsIsEmpty(uint256 constantsLength) external view { | ||
| constantsLength = bound(constantsLength, 1, type(uint256).max); | ||
| bytes memory serialized = new bytes(0x40); | ||
| assembly ("memory-safe") { | ||
| mstore(add(serialized, 0x20), constantsLength) | ||
| } | ||
| assertEq(LibInterpreterStateDataContract.bytecodeOf(serialized).length, 0); | ||
| } | ||
|
Comment on lines
+315
to
+354
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use complete NatSpec tags on the newly added tests to satisfy audit policy. These new test doc comments are descriptive, but not fully tagged NatSpec entries as required by your test audit guideline. As per coding guidelines, " 🤖 Prompt for AI AgentsSource: Coding guidelines
Comment on lines
+340
to
+354
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add a malformed bytecode-length overrun test case. Current edge tests cover short blobs and constants overruns, but not a blob where constants are in-bounds and the embedded bytecode length overruns the payload. 🤖 Prompt for AI Agents |
||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: rainlanguage/rainlang
Length of output: 2349
🏁 Script executed:
Repository: rainlanguage/rainlang
Length of output: 8183
🏁 Script executed:
Repository: rainlanguage/rainlang
Length of output: 14401
Add a bytecode-length bounds check in
LibInterpreterStateDataContract.bytecodeOf(lines 156-169).bytecodeOfonly bounds-checksconstantsLengthto ensure the bytecode length word is in-range, but it never validates the embeddedbytecodeLengthagainst the remaining bytes inserialized. A malformed blob can therefore return an in-placebytesslice with an oversized length, causing out-of-bounds reads/leaky ABI encoding when callers use the result.Guard
bytecodeLengthbefore returningbcby loading it fromserializedatbytecodeOffset = 0x40 + constantsLength * 0x20and returning""unlessbytecodeLength <= serialized.length - bytecodeOffset.🤖 Prompt for AI Agents