Hey @prestwich @ErinHales!
I've found an interesting bug in the isValid function of the TypedMemView library.
function isValid(bytes29 memView) internal pure returns (bool ret) {
if (typeOf(memView) == 0xffffffffff) {return false;}
uint256 _end = end(memView);
assembly {
// solium-disable-previous-line security/no-inline-assembly
ret := not(gt(_end, mload(0x40)))
}
}
The function is expected to return true when the memView data structure points to an allocated memory and false otherwise.
However, the function always returns true because the not operator does bitwise not and anything greater than zero is converted to the boolean value of true. Thus whatever the result of the gt operator is (zero or one) the functions returns true.
Impact
The isValid function is used in multiple other functions throughout the library and used to ensure the memory-safety guarantees of the library. Since the function always returns true these memory-safety guarantees break.
Unfortunately, I didn't have enough time&energy now to explore the impact on the Nomad project, where the library is used extensively, or other projects affected by the bug (some of which are quite popular: https://github.com/summa-tx/memview-sol/network/dependents).
Recommendation
Use the iszero operator instead of the not operator to invert a boolean value in assembly.
References
Proof of Concept
Here is a toy example to test this (you may copy-paste it to Remix IDE, deploy, and execute there).
pragma solidity 0.8.18;
contract poc {
function f() external pure returns (bool o0, bool o1, bool o2) {
assembly {
o0 := not(0)
o1 := not(1)
o2 := not(1337)
}
require(o0);
require(o1);
require(o2);
}
}
The f functions returns three true values.
Hey @prestwich @ErinHales!
I've found an interesting bug in the isValid function of the TypedMemView library.
The function is expected to return true when the
memViewdata structure points to an allocated memory and false otherwise.However, the function always returns true because the
notoperator does bitwisenotand anything greater than zero is converted to the boolean value of true. Thus whatever the result of thegtoperator is (zero or one) the functions returns true.Impact
The
isValidfunction is used in multiple other functions throughout the library and used to ensure the memory-safety guarantees of the library. Since the function always returns true these memory-safety guarantees break.Unfortunately, I didn't have enough time&energy now to explore the impact on the Nomad project, where the library is used extensively, or other projects affected by the bug (some of which are quite popular: https://github.com/summa-tx/memview-sol/network/dependents).
Recommendation
Use the
iszerooperator instead of thenotoperator to invert a boolean value in assembly.References
Proof of Concept
Here is a toy example to test this (you may copy-paste it to Remix IDE, deploy, and execute there).
The
ffunctions returns three true values.