Skip to content

Commit f6c9d14

Browse files
committed
Merge branch 'master' of github.com:GNSPS/solidity-bytes-utils
2 parents 406e282 + 916de66 commit f6c9d14

File tree

2 files changed

+33
-11
lines changed

2 files changed

+33
-11
lines changed

README.md

+13-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,19 @@ The library lets you concatenate, slice and type cast bytes arrays both in memor
88

99
Given this library has an all-internal collection of methods it doesn't make sense having it reside in the mainnet. Instead it will only be available in EPM as an installable package.
1010

11-
_Version Notes_:
11+
## Important Fixes Changelog
12+
13+
There was a **critical bug** in the `slice` method, reported on an audit to a DXDao codebase.
14+
15+
Previously, no checks were being made on overflows of the `_start` and `_length` parameters since previous reviews of the codebase deemed this overflow "unexploitable" because of an inordinate expansion of memory (i.e., reading an immensely large memory offset causing huge memory expansion) resulting in an out-of-gas exception.
16+
17+
However, as noted in the review mentioned above, this is not the case. The `slice` method in versions `<=0.9.0` actually allows for arbitrary _kind of_ (i.e., it allows memory writes to very specific values) arbitrary memory writes _in the specific case where these parameters are user-supplied inputs and not hardcoded values (which is uncommon).
18+
19+
This made me realize that in permissioned blockchains where gas is also not a limiting factor this could become problematic in other methods and so I updated all typecasting-related methods to include new bound checks as well.
20+
21+
**TL;DR: if you're using the `slice` method with user-supplied inputs in your codebase please update the bytes library immediately!**
22+
23+
## _Version Notes_:
1224

1325
* Version `v0.9.0` now compiles with Solidity compilers `0.5.x` and `0.6.x`.
1426

contracts/BytesLib.sol

+20-10
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,8 @@ library BytesLib {
234234
pure
235235
returns (bytes memory)
236236
{
237-
require(_bytes.length >= (_start + _length), "Read out of bounds");
237+
require(_start + _length + 31 >= _start, "slice_overflow");
238+
require(_bytes.length >= _start + _length, "slice_outOfBounds");
238239

239240
bytes memory tempBytes;
240241

@@ -291,7 +292,8 @@ library BytesLib {
291292
}
292293

293294
function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {
294-
require(_bytes.length >= (_start + 20), "Read out of bounds");
295+
require(_start + 20 >= _start, "toAddress_overflow");
296+
require(_bytes.length >= _start + 20, "toAddress_outOfBounds");
295297
address tempAddress;
296298

297299
assembly {
@@ -302,7 +304,8 @@ library BytesLib {
302304
}
303305

304306
function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) {
305-
require(_bytes.length >= (_start + 1), "Read out of bounds");
307+
require(_start + 1 >= _start, "toUint8_overflow");
308+
require(_bytes.length >= _start + 1 , "toUint8_outOfBounds");
306309
uint8 tempUint;
307310

308311
assembly {
@@ -313,7 +316,8 @@ library BytesLib {
313316
}
314317

315318
function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) {
316-
require(_bytes.length >= (_start + 2), "Read out of bounds");
319+
require(_start + 2 >= _start, "toUint16_overflow");
320+
require(_bytes.length >= _start + 2, "toUint16_outOfBounds");
317321
uint16 tempUint;
318322

319323
assembly {
@@ -324,7 +328,8 @@ library BytesLib {
324328
}
325329

326330
function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) {
327-
require(_bytes.length >= (_start + 4), "Read out of bounds");
331+
require(_start + 4 >= _start, "toUint32_overflow");
332+
require(_bytes.length >= _start + 4, "toUint32_outOfBounds");
328333
uint32 tempUint;
329334

330335
assembly {
@@ -335,7 +340,8 @@ library BytesLib {
335340
}
336341

337342
function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) {
338-
require(_bytes.length >= (_start + 8), "Read out of bounds");
343+
require(_start + 8 >= _start, "toUint64_overflow");
344+
require(_bytes.length >= _start + 8, "toUint64_outOfBounds");
339345
uint64 tempUint;
340346

341347
assembly {
@@ -346,7 +352,8 @@ library BytesLib {
346352
}
347353

348354
function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) {
349-
require(_bytes.length >= (_start + 12), "Read out of bounds");
355+
require(_start + 12 >= _start, "toUint96_overflow");
356+
require(_bytes.length >= _start + 12, "toUint96_outOfBounds");
350357
uint96 tempUint;
351358

352359
assembly {
@@ -357,7 +364,8 @@ library BytesLib {
357364
}
358365

359366
function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) {
360-
require(_bytes.length >= (_start + 16), "Read out of bounds");
367+
require(_start + 16 >= _start, "toUint128_overflow");
368+
require(_bytes.length >= _start + 16, "toUint128_outOfBounds");
361369
uint128 tempUint;
362370

363371
assembly {
@@ -368,7 +376,8 @@ library BytesLib {
368376
}
369377

370378
function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) {
371-
require(_bytes.length >= (_start + 32), "Read out of bounds");
379+
require(_start + 32 >= _start, "toUint256_overflow");
380+
require(_bytes.length >= _start + 32, "toUint256_outOfBounds");
372381
uint256 tempUint;
373382

374383
assembly {
@@ -379,7 +388,8 @@ library BytesLib {
379388
}
380389

381390
function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) {
382-
require(_bytes.length >= (_start + 32), "Read out of bounds");
391+
require(_start + 32 >= _start, "toBytes32_overflow");
392+
require(_bytes.length >= _start + 32, "toBytes32_outOfBounds");
383393
bytes32 tempBytes32;
384394

385395
assembly {

0 commit comments

Comments
 (0)