hats-finance / SeeR-PM-0x899bc13919880db76edf4ccd72bdfa5dfa666fb7

1 stars 0 forks source link

Overflow in Router `getPartition `Function for Large Outcome Sets #55

Open hats-bug-reporter[bot] opened 2 months ago

hats-bug-reporter[bot] commented 2 months ago

Github username: -- Twitter username: -- Submission hash (on-chain): 0xb14941a4db0c2da3549f36310cc673fa7fd582fc30aa52a6c1e86bb79d1b3ea7 Severity: medium

Description:

  1. Proof of Concept (PoC) file:
Outcome Index Binary Representation Decimal Value
254 0100000...0000000000 2^254
255 1000000...0000000000 2^255
256 0000000...0000000000 0 (Overflow occurs here)
257 0000000...0000000000 0
258 0000000...0000000000 0
259 0000000...0000000000 0
... ... ...

Explanation: │ | │ Safe range (0-255) │ Overflow range (256+) │ │ │ Each bit shifts left │ Bits is out of bound in bytes32 slot │ 1, 2, 4, 8, ..., 2^255 │ 0, 0, 0, 0, ... (repeats) │ │ └─────────────────────────────┴───────────────────────────────────────── 256-bit uint256 value

$ Overflow: When i >= 256, (1 << i) wraps around to small values, repeating the pattern of powers of 2 from the beginning.

// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

contract VulnerableRouter {
    function getPartition(uint256 size) public pure returns (uint256[] memory) {
        uint256[] memory partition = new uint256[](size);
        for (uint256 i = 0; i < size; i++) {
            partition[i] = 1 << i; // Overflow occurs when i >= 256
        }
        return partition;
    }

    function demonstrateOverflow(uint256 size) public pure returns (uint256[] memory) {
        require(size > 256, "Size must be greater than 256 to demonstrate overflow");
        return getPartition(size);
    }
}
  1. Revised Code File:
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

contract SafeRouter {
    function getPartition(uint256 size) public pure returns (uint256[] memory) {
+       require(size <= 256, "Outcome count exceeds maximum safe limit");
        uint256[] memory partition = new uint256[](size);
        for (uint256 i = 0; i < size; i++) {
            partition[i] = 1 << i;
        }
        return partition;
    }
}
Rassska commented 2 months ago

there will not be more than 256 outcomes

greenlucid commented 2 months ago

https://github.com/seer-pm/demo/blob/4e56254cbd071b6f678a108ccdb8660951636d27/contracts/src/interaction/conditional-tokens/ConditionalTokens.sol#L75

clesaege commented 2 months ago

Yeah, this limit is enforced by ConditionalTokens.