From d3c84f5b05993cfb5b630b69f4fe8bea9a8d31ac Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Tue, 4 Nov 2025 14:18:05 +0100 Subject: [PATCH 1/2] Fix byte lookup when decoding length of RLP structure --- contracts/utils/RLP.sol | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/contracts/utils/RLP.sol b/contracts/utils/RLP.sol index 19572acf431..f62491e0f54 100644 --- a/contracts/utils/RLP.sol +++ b/contracts/utils/RLP.sol @@ -351,7 +351,7 @@ library RLP { // Case: Long string (>55 bytes) uint256 lengthLength = prefix - SHORT_OFFSET - SHORT_THRESHOLD; - require(itemLength > lengthLength && bytes1(item.load(0)) != 0x00, RLPInvalidEncoding()); + require(itemLength > lengthLength && bytes1(item.load(1)) != 0x00, RLPInvalidEncoding()); uint256 len = uint256(item.load(1)) >> (256 - 8 * lengthLength); require(len > SHORT_THRESHOLD && itemLength > lengthLength + len, RLPInvalidEncoding()); @@ -369,8 +369,7 @@ library RLP { // Case: Long list uint256 lengthLength = prefix - LONG_OFFSET - SHORT_THRESHOLD; - require(itemLength > lengthLength, RLPInvalidEncoding()); - require(bytes1(item.load(0)) != 0x00); + require(itemLength > lengthLength && bytes1(item.load(1)) != 0x00, RLPInvalidEncoding()); uint256 len = uint256(item.load(1)) >> (256 - 8 * lengthLength); require(len > SHORT_THRESHOLD && itemLength > lengthLength + len, RLPInvalidEncoding()); From 3e962351be968d527ec27b860595a1a710449a73 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Tue, 4 Nov 2025 14:24:59 +0100 Subject: [PATCH 2/2] cache load --- .changeset/yellow-clowns-mate.md | 5 +++++ contracts/utils/RLP.sol | 10 ++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 .changeset/yellow-clowns-mate.md diff --git a/.changeset/yellow-clowns-mate.md b/.changeset/yellow-clowns-mate.md new file mode 100644 index 00000000000..3372a8d2eef --- /dev/null +++ b/.changeset/yellow-clowns-mate.md @@ -0,0 +1,5 @@ +--- +'openzeppelin-solidity': patch +--- + +`RLP`: Fix RLP encoding validity check when decoding long lists or strings diff --git a/contracts/utils/RLP.sol b/contracts/utils/RLP.sol index f62491e0f54..5347be2fcd8 100644 --- a/contracts/utils/RLP.sol +++ b/contracts/utils/RLP.sol @@ -351,9 +351,10 @@ library RLP { // Case: Long string (>55 bytes) uint256 lengthLength = prefix - SHORT_OFFSET - SHORT_THRESHOLD; - require(itemLength > lengthLength && bytes1(item.load(1)) != 0x00, RLPInvalidEncoding()); + bytes32 lenChunk = item.load(1); + require(itemLength > lengthLength && bytes1(lenChunk) != 0x00, RLPInvalidEncoding()); - uint256 len = uint256(item.load(1)) >> (256 - 8 * lengthLength); + uint256 len = uint256(lenChunk) >> (256 - 8 * lengthLength); require(len > SHORT_THRESHOLD && itemLength > lengthLength + len, RLPInvalidEncoding()); return (lengthLength + 1, len, ItemType.Data); @@ -369,9 +370,10 @@ library RLP { // Case: Long list uint256 lengthLength = prefix - LONG_OFFSET - SHORT_THRESHOLD; - require(itemLength > lengthLength && bytes1(item.load(1)) != 0x00, RLPInvalidEncoding()); + bytes32 lenChunk = item.load(1); + require(itemLength > lengthLength && bytes1(lenChunk) != 0x00, RLPInvalidEncoding()); - uint256 len = uint256(item.load(1)) >> (256 - 8 * lengthLength); + uint256 len = uint256(lenChunk) >> (256 - 8 * lengthLength); require(len > SHORT_THRESHOLD && itemLength > lengthLength + len, RLPInvalidEncoding()); return (lengthLength + 1, len, ItemType.List);