Skip to content

Commit

Permalink
reduce max offset to 2^30 - 1; refactor TupleType#decode;
Browse files Browse the repository at this point in the history
  • Loading branch information
esaulpaugh committed Oct 29, 2024
1 parent 71f3f60 commit 1520478
Show file tree
Hide file tree
Showing 4 changed files with 11 additions and 12 deletions.
2 changes: 1 addition & 1 deletion src/main/java/com/esaulpaugh/headlong/abi/ArrayType.java
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ private E[] decodeObjects(int len, ByteBuffer bb, byte[] unitBuffer) {
int saved = start;
for ( ; i < elements.length; i++) {
bb.position(saved);
final int jump = start + IntType.UINT31.decode(bb, unitBuffer);
final int jump = start + IntType.UINT30.decode(bb, unitBuffer);
/* LENIENT MODE; see https://github.com/ethereum/solidity/commit/3d1ca07e9b4b42355aa9be5db5c00048607986d1 */
saved = bb.position();
bb.position(jump); // leniently jump to specified offset
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/esaulpaugh/headlong/abi/IntType.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
public final class IntType extends UnitType<Integer> {

static final IntType UINT21 = new IntType("uint21", 21, true); // small bit length for Denial-of-Service protection
static final IntType UINT31 = new IntType("uint31", 31, true);
static final IntType UINT30 = new IntType("uint30", 30, true);

static {
UnitType.initInstances(); // will prevent creation of new UnitTypes once finished (except BigDecimalType)
Expand Down
11 changes: 5 additions & 6 deletions src/main/java/com/esaulpaugh/headlong/abi/TupleType.java
Original file line number Diff line number Diff line change
Expand Up @@ -253,18 +253,17 @@ J decode(ByteBuffer bb, byte[] unitBuffer) {
if (!t.dynamic) {
elements[i] = t.decode(bb, unitBuffer);
} else {
final int offset = IntType.UINT31.decode(bb, unitBuffer);
offsets[i] = offset == 0 ? -1 : offset;
offsets[i] = IntType.UINT30.decode(bb, unitBuffer) + 1; // read as 30-bit unsigned--no overflow possible
}
} while (++i < elements.length);
i = 0;
do {
final int offset = offsets[i];
if (offset != 0) {
final int jump = start + offset;
if (offset != 0) { // use != instead of > so as to tolerate any potential overflow/wraparound in the future
final int jump = start + offset - 1;
if (jump != bb.position()) { // && (this.flags & ABIType.FLAG_LEGACY_ARRAY) == 0
/* LENIENT MODE; see https://github.com/ethereum/solidity/commit/3d1ca07e9b4b42355aa9be5db5c00048607986d1 */
bb.position(offset == -1 ? start : jump); // leniently jump to specified offset
bb.position(jump); // leniently jump to specified offset
}
elements[i] = get(i).decode(bb, unitBuffer);
}
Expand Down Expand Up @@ -302,7 +301,7 @@ private Object decodeIndex(ByteBuffer bb, int start, byte[] unitBuffer, int i) {
final ABIType<?> t = get(i);
bb.position(start + elementHeadOffsets[i]);
if (t.dynamic) {
bb.position(start + IntType.UINT31.decode(bb, unitBuffer));
bb.position(start + IntType.UINT30.decode(bb, unitBuffer));
}
return t.decode(bb, unitBuffer);
} catch (IllegalArgumentException cause) {
Expand Down
8 changes: 4 additions & 4 deletions src/test/java/com/esaulpaugh/headlong/abi/DecodeTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -173,24 +173,24 @@ public void testDoSLimit() throws Throwable {
);

final String bigOffset =
"000000000000000000000000000000000000000000000000000000007FFFFFFF" +
"000000000000000000000000000000000000000000000000000000003FFFFFFF" +
"0000000000000000000000000000000000000000000000000000000000000001" +
"aa00000000000000000000000000000000000000000000000000000000000000";
assertThrownWithAnySubstring(
IllegalArgumentException.class,
Arrays.asList(
"tuple index 0: newPosition > limit: (2147483647 > 96)",
"tuple index 0: newPosition > limit: (1073741823 > 96)",
"tuple index 0: null"
),
() -> Function.parse("()", "(bytes)").decodeReturn(Strings.decode(bigOffset))
);
final String tooBigOffset =
"0000000000000000000000000000000000000000000000000000000080000000" +
"0000000000000000000000000000000000000000000000000000000040000000" +
"0000000000000000000000000000000000000000000000000000000000000001" +
"aa00000000000000000000000000000000000000000000000000000000000000";
assertThrown(
IllegalArgumentException.class,
"exceeds bit limit: 32 > 31",
"tuple index 0: unsigned val exceeds bit limit: 31 > 30",
() -> Function.parse("()", "(bytes)").decodeReturn(Strings.decode(tooBigOffset))
);

Expand Down

0 comments on commit 1520478

Please sign in to comment.