-
Notifications
You must be signed in to change notification settings - Fork 12.2k
Add RLP library #5680
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
base: master
Are you sure you want to change the base?
Add RLP library #5680
Changes from all commits
9eb5f1c
2d397f4
2a0fb7e
a7e61c3
1aae8bb
1b2679a
d514606
14fa04e
d0d55fc
7b3cb66
95149f8
ad5d4ac
18540ef
163f27c
c484289
e0d4790
a6f9053
e2b5e4c
203d1a2
48eabc1
63ced95
f342756
23dba37
0cacca2
831e8ab
5da111f
ba2293e
9409bc6
e740dac
0332ffe
608e3cd
ac92bb4
6094bb7
6bb96d5
860e5a8
ecdb768
95907aa
124ccee
c3237df
27f0a9b
282ce39
bdd2cf1
42c79f1
5754ab8
44f0e14
05c73bd
3a6fbf6
e67e8b4
3385718
40d7922
89860bc
9b58730
77ffa8c
ce91c80
b3e3add
2f3107c
4383e01
5a44b11
d6db2d7
3847050
4fd1947
c4e0375
acb14cb
2208006
13f4d8f
502a520
aab9274
aa26e48
948f0a1
d4bfb8b
138de7f
5efeb37
00ff228
c58c7fd
d1aa944
0925577
590b7d7
8928039
bb027df
ec4a5c1
b75dc7c
fc208c8
fe0597c
106764e
b55b1db
e490d79
bde8251
8b6ea8c
dba642d
5e3ce7c
4d39206
902b222
b301b06
1b112b2
9c0e924
c48e623
b10ae8c
d411318
df528af
da61a5e
fadc8ac
283ce7c
5561d52
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 |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'openzeppelin-solidity': minor | ||
--- | ||
|
||
`RLP`: Add library for Ethereum's Recursive Length Prefix encoding/decoding. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,8 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.20; | ||
pragma solidity ^0.8.24; | ||
|
||
import {Panic} from "./Panic.sol"; | ||
|
||
/** | ||
* @dev Utilities to manipulate memory. | ||
|
@@ -41,4 +43,71 @@ library Memory { | |
function asPointer(bytes32 value) internal pure returns (Pointer) { | ||
return Pointer.wrap(value); | ||
} | ||
|
||
type Slice is bytes32; | ||
|
||
/// @dev Get a slice representation of a bytes object in memory | ||
function asSlice(bytes memory self) internal pure returns (Slice result) { | ||
assembly ("memory-safe") { | ||
result := or(shl(128, mload(self)), add(self, 0x20)) | ||
} | ||
} | ||
|
||
/// @dev Private helper: create a slice from raw values (length and pointer) | ||
function _asSlice(uint256 len, Memory.Pointer ptr) private pure returns (Slice result) { | ||
// TODO: Fail if len or ptr is larger than type(uint128).max ? | ||
assembly ("memory-safe") { | ||
result := or(shl(128, len), ptr) | ||
} | ||
} | ||
Comment on lines
+58
to
+62
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 bounds validation for length and pointer values. The TODO comment correctly identifies a potential issue. Values exceeding Apply this fix to add validation: function _asSlice(uint256 len, Memory.Pointer ptr) private pure returns (Slice result) {
- // TODO: Fail if len or ptr is larger than type(uint128).max ?
+ require(len <= type(uint128).max, "Length exceeds uint128 max");
+ require(uint256(asBytes32(ptr)) <= type(uint128).max, "Pointer exceeds uint128 max");
assembly ("memory-safe") {
result := or(shl(128, len), ptr)
}
}
🤖 Prompt for AI Agents
|
||
|
||
/// @dev Returns the memory location of a given slice (equiv to self.offset for calldata slices) | ||
function _pointer(Slice self) private pure returns (Memory.Pointer result) { | ||
assembly ("memory-safe") { | ||
result := and(self, shr(128, not(0))) | ||
} | ||
} | ||
|
||
/// @dev Returns the length of a given slice (equiv to self.length for calldata slices) | ||
function length(Slice self) internal pure returns (uint256 result) { | ||
assembly ("memory-safe") { | ||
result := shr(128, self) | ||
} | ||
} | ||
|
||
/// @dev Offset a memory slice (equivalent to self[start:] for calldata slices) | ||
function slice(Slice self, uint256 offset) internal pure returns (Slice) { | ||
if (offset > length(self)) Panic.panic(Panic.ARRAY_OUT_OF_BOUNDS); | ||
return _asSlice(length(self) - offset, asPointer(bytes32(uint256(asBytes32(_pointer(self))) + offset))); | ||
} | ||
|
||
/// @dev Offset and cut a Slice (equivalent to self[start:start+length] for calldata slices) | ||
function slice(Slice self, uint256 offset, uint256 len) internal pure returns (Slice) { | ||
if (offset + len > length(self)) Panic.panic(Panic.ARRAY_OUT_OF_BOUNDS); | ||
return _asSlice(len, asPointer(bytes32(uint256(asBytes32(_pointer(self))) + offset))); | ||
} | ||
|
||
/** | ||
* @dev Read a bytes32 buffer from a given Slice at a specific offset | ||
* | ||
* Note:If offset > length(slice) - 32, part of the return value will be out of bound and should be ignored. | ||
*/ | ||
function load(Slice self, uint256 offset) internal pure returns (bytes32 value) { | ||
if (offset >= length(self)) Panic.panic(Panic.ARRAY_OUT_OF_BOUNDS); | ||
assembly ("memory-safe") { | ||
value := mload(add(and(self, shr(128, not(0))), offset)) | ||
} | ||
} | ||
|
||
/// @dev Extract the data corresponding to a Slice (allocate new memory) | ||
function toBytes(Slice self) internal pure returns (bytes memory result) { | ||
uint256 len = length(self); | ||
Memory.Pointer ptr = _pointer(self); | ||
assembly ("memory-safe") { | ||
result := mload(0x40) | ||
mstore(result, len) | ||
mcopy(add(result, 0x20), ptr, len) | ||
mstore(0x40, add(add(result, len), 0x20)) | ||
} | ||
} | ||
} |
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.
Bug: free memory pointer not 32‑byte aligned in flatten().
FMP must be rounded up to the next 32‑byte boundary. Writing
mstore(0x40, ptr)
leaves it potentially unaligned and can corrupt subsequent allocations.Apply this diff:
📝 Committable suggestion
🤖 Prompt for AI Agents