Skip to content

Commit

Permalink
Add bounds check to Uint16Array (#1017)
Browse files Browse the repository at this point in the history
  • Loading branch information
alistair-singh authored Nov 23, 2023
1 parent eb13b90 commit d97e3b7
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 2 deletions.
19 changes: 17 additions & 2 deletions contracts/src/utils/Uint16Array.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,27 @@ pragma solidity 0.8.22;
* then to bit-index 128 to 143 of uint256[1].
*/
library Uint16Array {
/**
* @dev stores the backing array and the length.
*/
struct Array {
uint256[] data;
uint256 length;
}

/**
* @dev error for when out of bound accesses occur.
*/
error IndexOutOfBounds();

/**
* @dev Creates a new counter which can store at least `length` counters.
* @param length The amount of counters.
*/

function create(uint256 length) internal pure returns (Array memory) {
// create space for `length` elements and round up if needed.
uint256 bufferLength = length / 16 + (length % 16 == 0 ? 0 : 1);
return Array({data: new uint256[](bufferLength)});
return Array({data: new uint256[](bufferLength), length: length});
}

/**
Expand All @@ -50,6 +59,9 @@ library Uint16Array {
* @param index The logical index.
*/
function get(Array storage self, uint256 index) internal view returns (uint16) {
if (index >= self.length) {
revert IndexOutOfBounds();
}
// Right-shift the index by 4. This truncates the first 4 bits (bit-index) leaving us with the index
// into the array.
uint256 element = index >> 4;
Expand All @@ -66,6 +78,9 @@ library Uint16Array {
* @param value The value to set the counter to.
*/
function set(Array storage self, uint256 index, uint16 value) internal {
if (index >= self.length) {
revert IndexOutOfBounds();
}
// Right-shift the index by 4. This truncates the first 4 bits (bit-index) leaving us with the index
// into the array.
uint256 element = index >> 4;
Expand Down
12 changes: 12 additions & 0 deletions contracts/test/Uint16Array.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,16 @@ contract Uint16ArrayTest is Test {
console.log("round2:index at %d set %d and get %d", index, value, new_value);
assertEq(value, new_value);
}

function testCounterGetOutOfBounds() public {
counters = Uint16Array.create(17);
vm.expectRevert(Uint16Array.IndexOutOfBounds.selector);
counters.get(17);
}

function testCounterSetOutOfBounds() public {
counters = Uint16Array.create(17);
vm.expectRevert(Uint16Array.IndexOutOfBounds.selector);
counters.set(17, 1);
}
}

0 comments on commit d97e3b7

Please sign in to comment.