argotorg / argotorg/solcore

abi_decode doesn't correctly decode arrays of uint256

Open Beginner friendly
#578 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Haskell
Stars
113
Forks
9
Avg merge
4d 9h
Merged PRs (30d)
1

Description

BUG: after fixing the buffer origin, the public abi_decode function reaches the array decoder correctly.
That decoder mistakes the top-level offset (32) for the array length and never decodes the elements.
Expected result: (3, 11). Actual result: (32, 0).

```solidity
import std.{*};
import std.dispatch.{*};
import std.opcodes.{mload};

// workaround for https://github.com/argotorg/solcore/issues/577
// A local view of memory(bytes) with the AbiDecodeBufferOrigin fix applied.
// Its WordReader begins at [payload], not at [length | payload].
data PayloadMemoryBytes = PayloadMemoryBytes(word);

instance PayloadMemoryBytes:HasWordReader(MemoryWordReader) {
function getWordReader(x: PayloadMemoryBytes) -> MemoryWordReader {
match x {
| PayloadMemoryBytes(ptr) => return MemoryWordReader(ptr + 32);
}
}
}
contract MemoryArrayDecoder {
public function decodeArray() -> (uint256, uint256) {
let original: memory(DynArray(uint256)) = [11, 22, 33];
let encoded = abi_encode(original);
let fixedInput = PayloadMemoryBytes(Typedef.rep(encoded));
let decoded: memory(DynArray(uint256)) = abi_decode(
fixedInput,
Proxy:Proxy(memory(DynArray(uint256))),
Proxy:Proxy(MemoryWordReader)
);
return (uint256(mload(Typedef.rep(decoded))), decoded[uint256(0)]);
}
}
```

SOLUTION: have the memory-array decoder follow the top-level dynamic offset, read the tail length, and restore its element loop.
Decode each element from the array-region base so offsets for dynamic elements remain relative to thecorrect origin;
reject unsupported element layouts instead of returning zeros.

PATCH: https://github.com/argotorg/solcore-rs/blob/8d5576699a8ca139e43b72c39f4545d3d2312de1/std/std.solc#L1707
```diff
- let arrayPtr = WordReader.advance(ptr, currentHeadOffset);
+ let tail = WordReader.read(WordReader.advance(ptr, currentHeadOffset));
+ let arrayPtr = WordReader.advance(ptr, tail); // then restore the decode loop
```

Contributor guide

No contributing guide indexed for this repository

Research direction

Start in std/std.solc around line 1707 and reproduce the issue through MemoryArrayDecoder.decodeArray using the example in the report. Verify that the decoded array returns (3, 11), that its elements are read from the correct array region, and that unsupported element layouts do not silently return zeros.

Written by the indexing model from the issue text.

Assessment

Tech stack
solidity
Domain
compilers
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
82/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.