diff --git a/contracts/AssertBytes.sol b/contracts/AssertBytes.sol index a26b6f9..2abc508 100755 --- a/contracts/AssertBytes.sol +++ b/contracts/AssertBytes.sol @@ -105,40 +105,42 @@ library AssertBytes { // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage - switch lt(slength, 32) - case 1 { - // blank the last byte which is the length - fslot := mul(div(fslot, 0x100), 0x100) + if iszero(iszero(slength)) { + switch lt(slength, 32) + case 1 { + // blank the last byte which is the length + fslot := mul(div(fslot, 0x100), 0x100) - if iszero(eq(fslot, mload(add(_b, 0x20)))) { - // unsuccess: - returnBool := 0 - } - } - default { - // cb is a circuit breaker in the for loop since there's - // no said feature for inline assembly loops - // cb = 1 - don't breaker - // cb = 0 - break - let cb := 1 - - // get the keccak hash to get the contents of the array - mstore(0x0, _a_slot) - let sc := keccak256(0x0, 0x20) - - let mc := add(_b, 0x20) - let end := add(mc, mlength) - - // the next line is the loop condition: - // while(uint(mc < end) + cb == 2) - for {} eq(add(lt(mc, end), cb), 2) { - sc := add(sc, 1) - mc := add(mc, 0x20) - } { - if iszero(eq(sload(sc), mload(mc))) { + if iszero(eq(fslot, mload(add(_b, 0x20)))) { // unsuccess: returnBool := 0 - cb := 0 + } + } + default { + // cb is a circuit breaker in the for loop since there's + // no said feature for inline assembly loops + // cb = 1 - don't breaker + // cb = 0 - break + let cb := 1 + + // get the keccak hash to get the contents of the array + mstore(0x0, _a_slot) + let sc := keccak256(0x0, 0x20) + + let mc := add(_b, 0x20) + let end := add(mc, mlength) + + // the next line is the loop condition: + // while(uint(mc < end) + cb == 2) + for {} eq(add(lt(mc, end), cb), 2) { + sc := add(sc, 1) + mc := add(mc, 0x20) + } { + if iszero(eq(sload(sc), mload(mc))) { + // unsuccess: + returnBool := 0 + cb := 0 + } } } } diff --git a/contracts/BytesLib.sol b/contracts/BytesLib.sol index 0de2556..2adba64 100755 --- a/contracts/BytesLib.sol +++ b/contracts/BytesLib.sol @@ -271,40 +271,42 @@ library BytesLib { // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage - switch lt(slength, 32) - case 1 { - // blank the last byte which is the length - fslot := mul(div(fslot, 0x100), 0x100) + if iszero(iszero(slength)) { + switch lt(slength, 32) + case 1 { + // blank the last byte which is the length + fslot := mul(div(fslot, 0x100), 0x100) - if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) { - // unsuccess: - success := 0 - } - } - default { - // cb is a circuit breaker in the for loop since there's - // no said feature for inline assembly loops - // cb = 1 - don't breaker - // cb = 0 - break - let cb := 1 - - // get the keccak hash to get the contents of the array - mstore(0x0, _preBytes_slot) - let sc := keccak256(0x0, 0x20) - - let mc := add(_postBytes, 0x20) - let end := add(mc, mlength) - - // the next line is the loop condition: - // while(uint(mc < end) + cb == 2) - for {} eq(add(lt(mc, end), cb), 2) { - sc := add(sc, 1) - mc := add(mc, 0x20) - } { - if iszero(eq(sload(sc), mload(mc))) { + if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) { // unsuccess: success := 0 - cb := 0 + } + } + default { + // cb is a circuit breaker in the for loop since there's + // no said feature for inline assembly loops + // cb = 1 - don't breaker + // cb = 0 - break + let cb := 1 + + // get the keccak hash to get the contents of the array + mstore(0x0, _preBytes_slot) + let sc := keccak256(0x0, 0x20) + + let mc := add(_postBytes, 0x20) + let end := add(mc, mlength) + + // the next line is the loop condition: + // while(uint(mc < end) + cb == 2) + for {} eq(add(lt(mc, end), cb), 2) { + sc := add(sc, 1) + mc := add(mc, 0x20) + } { + if iszero(eq(sload(sc), mload(mc))) { + // unsuccess: + success := 0 + cb := 0 + } } } } diff --git a/ethpm.json b/ethpm.json index 41cc749..3c97f15 100644 --- a/ethpm.json +++ b/ethpm.json @@ -1,6 +1,6 @@ { "package_name": "bytes", - "version": "0.0.2", + "version": "0.0.3", "description": "Solidity bytes tightly packed arrays utility library.", "authors": [ "Gonçalo Sá " diff --git a/package.json b/package.json index 6a4a54d..f4f3d6a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "solidity-bytes-utils", - "version": "0.0.2", + "version": "0.0.3", "description": "Solidity bytes tightly packed arrays utility library.", "main": "truffle.js", "repository": { diff --git a/test/TestBytesLib1.sol b/test/TestBytesLib1.sol index d0d6695..393498a 100755 --- a/test/TestBytesLib1.sol +++ b/test/TestBytesLib1.sol @@ -10,6 +10,7 @@ contract TestBytesLib1 { using BytesLib for bytes; bytes storageCheckBytes = hex"aabbccddeeff"; + bytes storageCheckBytesZeroLength = hex""; bytes storageBytes4 = hex"f00dfeed"; bytes storageBytes31 = hex"f00d000000000000000000000000000000000000000000000000000000feed"; @@ -28,16 +29,31 @@ contract TestBytesLib1 { function testSanityCheck() public { // Assert library sanity checks + // + // Please don't change the ordering of the var definitions + // the order is purposeful for testing zero-length arrays bytes memory checkBytes = hex"aabbccddeeff"; + bytes memory checkBytesZeroLength = hex""; bytes memory checkBytesRight = hex"aabbccddeeff"; - bytes memory checkBytesWrong = hex"000000"; + bytes memory checkBytesZeroLengthRight = hex""; + bytes memory checkBytesWrongLength = hex"aa0000"; + bytes memory checkBytesWrongContent = hex"aabbccddee00"; AssertBytes.equal(checkBytes, checkBytesRight, "Sanity check should be checking equal bytes arrays out."); - AssertBytes.notEqual(checkBytes, checkBytesWrong, "Sanity check should be checking different bytes arrays out."); + AssertBytes.notEqual(checkBytes, checkBytesWrongLength, "Sanity check should be checking different length bytes arrays out."); + AssertBytes.notEqual(checkBytes, checkBytesWrongContent, "Sanity check should be checking different content bytes arrays out."); - AssertBytes.equalStorage(storageCheckBytes, checkBytesRight, "Sanity check should be checking equal bytes arrays out."); - AssertBytes.notEqualStorage(storageCheckBytes, checkBytesWrong, "Sanity check should be checking different bytes arrays out."); + AssertBytes.equalStorage(storageCheckBytes, checkBytesRight, "Sanity check should be checking equal bytes arrays out. (Storage)"); + AssertBytes.notEqualStorage(storageCheckBytes, checkBytesWrongLength, "Sanity check should be checking different length bytes arrays out. (Storage)"); + AssertBytes.notEqualStorage(storageCheckBytes, checkBytesWrongContent, "Sanity check should be checking different content bytes arrays out. (Storage)"); + + // Zero-length checks + AssertBytes.equal(checkBytesZeroLength, checkBytesZeroLengthRight, "Sanity check should be checking equal zero-length bytes arrays out."); + AssertBytes.notEqual(checkBytesZeroLength, checkBytes, "Sanity check should be checking different length bytes arrays out."); + + AssertBytes.equalStorage(storageCheckBytesZeroLength, checkBytesZeroLengthRight, "Sanity check should be checking equal zero-length bytes arrays out. (Storage)"); + AssertBytes.notEqualStorage(storageCheckBytesZeroLength, checkBytes, "Sanity check should be checking different length bytes arrays out. (Storage)"); } /** diff --git a/test/TestBytesLib2.sol b/test/TestBytesLib2.sol index ca1adcd..cd2b1cc 100755 --- a/test/TestBytesLib2.sol +++ b/test/TestBytesLib2.sol @@ -10,6 +10,7 @@ contract TestBytesLib2 { using BytesLib for bytes; bytes storageCheckBytes = hex"aabbccddeeff"; + bytes storageCheckBytesZeroLength = hex""; /** * Sanity Checks @@ -17,16 +18,31 @@ contract TestBytesLib2 { function testSanityCheck() public { // Assert library sanity checks + // + // Please don't change the ordering of the var definitions + // the order is purposeful for testing zero-length arrays bytes memory checkBytes = hex"aabbccddeeff"; + bytes memory checkBytesZeroLength = hex""; bytes memory checkBytesRight = hex"aabbccddeeff"; - bytes memory checkBytesWrong = hex"000000"; + bytes memory checkBytesZeroLengthRight = hex""; + bytes memory checkBytesWrongLength = hex"aa0000"; + bytes memory checkBytesWrongContent = hex"aabbccddee00"; AssertBytes.equal(checkBytes, checkBytesRight, "Sanity check should be checking equal bytes arrays out."); - AssertBytes.notEqual(checkBytes, checkBytesWrong, "Sanity check should be checking different bytes arrays out."); + AssertBytes.notEqual(checkBytes, checkBytesWrongLength, "Sanity check should be checking different length bytes arrays out."); + AssertBytes.notEqual(checkBytes, checkBytesWrongContent, "Sanity check should be checking different content bytes arrays out."); - AssertBytes.equalStorage(storageCheckBytes, checkBytesRight, "Sanity check should be checking equal bytes arrays out."); - AssertBytes.notEqualStorage(storageCheckBytes, checkBytesWrong, "Sanity check should be checking different bytes arrays out."); + AssertBytes.equalStorage(storageCheckBytes, checkBytesRight, "Sanity check should be checking equal bytes arrays out. (Storage)"); + AssertBytes.notEqualStorage(storageCheckBytes, checkBytesWrongLength, "Sanity check should be checking different length bytes arrays out. (Storage)"); + AssertBytes.notEqualStorage(storageCheckBytes, checkBytesWrongContent, "Sanity check should be checking different content bytes arrays out. (Storage)"); + + // Zero-length checks + AssertBytes.equal(checkBytesZeroLength, checkBytesZeroLengthRight, "Sanity check should be checking equal zero-length bytes arrays out."); + AssertBytes.notEqual(checkBytesZeroLength, checkBytes, "Sanity check should be checking different length bytes arrays out."); + + AssertBytes.equalStorage(storageCheckBytesZeroLength, checkBytesZeroLengthRight, "Sanity check should be checking equal zero-length bytes arrays out. (Storage)"); + AssertBytes.notEqualStorage(storageCheckBytesZeroLength, checkBytes, "Sanity check should be checking different length bytes arrays out. (Storage)"); } /**