Not is not iszero
To start the blog I would like to share how the not
and iszero
instructions differ in Yul. This have led to discovery of two interesting low-severity bugs one of which is public so I am going to use it as an example to spread the knowledge about the difference.
The bug was found in the TypedMemView library. From the library’s README: “TypedMemView is a library for interacting with the EVM’s linear memory in Solidity. It provides safe access to contiguous portions of memory, in a C-like style. Views are stored on the stack, and may be manipulated without manipulating the underlying memory.”
Let us take a closer look at the isValid
function.
/**
* @notice Check if the view is of a valid type and points to a valid location
* in memory.
* @dev We perform this check by examining solidity's unallocated memory
* pointer and ensuring that the view's upper bound is less than that.
* @param memView The view
* @return ret - True if the view is valid
*/
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)))
}
}
What do you expect the function to return when _end
is less or equal to mload(0x40)
? What about the opposite case? Instinctively, I would say true and false respectively. In reality, the function always returns true! Why? The not
instruction in Yul means bitwise not so 1
becomes type(uint256).max - 1
and 0
becomes type(uint256).max
and the return value will be true
regardless of the input.
The impact of the bug was not obvious to me and I did not have enough time to dive deep but the library was used in some notable projects and the bug could potentially break some of its memory safety guarantees. So I decided to responsibly disclose the bug as is to the Nomad team because they use and maintain the library.
I reported the bug via Immunefi and then via GitHub Issues because Immunefi closed the report as out of scope and the maintainers gave the permission to open a public issue.
Remediation was simple: the not
instruction was replaced with iszero
.
Even though the library was out of scope the Nomad team still rewarded the finding. The reward was donated towards the Center for Contemplative Research.
Timeline
Date | Event |
---|---|
2023-02-15 | Bug reported to Nomad via Immunefi |
2023-02-15 | Report closed by Immunefi as out of scope |
2023-02-23 | Immunefi communicated that Nomad team allowed public bug report |
2023-02-23 | Bug reported to Nomad via GitHub Issues |
2023-02-23 | Fix applied |
2023-03-07 | Report reopened and reward issued |
2023-03-20 | Report closed and reward donated |
2023-04-08 | Permission to publish blog post requested |
2023-04-08 | Permission to publish blog post granted |