-
Notifications
You must be signed in to change notification settings - Fork 6.3k
Properly force-clean for shortening bytesXX conversions. #3868
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
This is weird, because we actually have a test for this: https://github.com/ethereum/solidity/blob/develop/test/libsolidity/SolidityEndToEndTest.cpp#L1580 |
|
Ok, I think I can see why this is still fine in most cases: Whenever we store in storage, we chop additional bits, so storage is safe. Whenever we store in memory, we do an additional cleanup, and for that additional cleanup, we either widen (implicit conversion) or we do not change the size at all. In both cases, the typeOnStack is the shorter one, so we do proper cleanup. The only case where this can be problematic that I can think of is: |
|
Doesn't the ABI encoder does cleaning on its own? A better test would be: |
| m_context << ((u256(1) << (256 - typeOnStack.numBytes() * 8)) - 1); | ||
| m_context << Instruction::NOT << Instruction::AND; | ||
| } | ||
| int bytes = min(typeOnStack.numBytes(), targetType.numBytes()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unsigned?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
numBytes() returns int.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, what case can numBytes be negative? Is that another oversight?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems to be an oversight since there's an assert forcing it to be unsigned: https://github.com/ethereum/solidity/blob/develop/libsolidity/ast/Types.cpp#L1146
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this is a very old line in the code. I guess the idea was that it is easier to subtract bytes or something.
axic
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to be rebased and remove the extra masking in abi.encode.
f3fe04f to
161ff5e
Compare
|
Finished. |
|
Will add documentation to inline assembly that states when accessing local variables, short types are not guaranteed to have clean higher order bits. |
|
Updated. |
erak
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me.
| To be safe, always clear the data properly before you use it | ||
| in a context where this is important: | ||
| ``uint32 x = f(); assembly { x := and(x, 0xffffffff) /* now use x */ }`` | ||
| To clean signed types, you can use the ``signextend`` opcode. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should have given an example.
| bytes4 x = 0xffffffff; | ||
| bytes2 y = bytes2(x); | ||
| assembly { r := y } | ||
| // At this point, r and y both store four bytes, but |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually wonder why shouldn't we properly apply the cleanup before the assembly block?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can actually check how the optimizer copes with cleanup done all the time.
Fixes #3867
It seems like the proper thing is done for integers, but not for bytesXX types.