-
Notifications
You must be signed in to change notification settings - Fork 5.9k
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
Use returndatacopy for retrieving dynamically sized outputs. #3308
Conversation
a023ade
to
aab2ac1
Compare
This is ready for review. Decisions to be taken:
|
else | ||
m_context << Instruction::POP; | ||
{ | ||
utils().fetchFreeMemoryPointer(); |
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 should add a size check here, too.
431379d
to
384115e
Compare
Hi guys. Is it still not merged? |
@AnthonyAkentiev someone is impatient there :) There are still security issues to be discussed, see above. |
The first comment above is solved ( |
Perhaps we could remove the |
Use the old decoder only on statically-sized data or on the statically-sized head of dynamically-sized data. This means returndatacopy is not used with the old decoder. |
// Alter dynamic types to be non-accessible. | ||
for (auto& param: returnParameterTypes) | ||
if (param->isDynamicallySized()) | ||
param = make_shared<InaccessibleDynamicType>(); |
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 could move this check into the TypeChecker
around line 1500.
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.
... only if the pragma specifies that we are using the old encoder.
Should use the new |
352cf60
to
5ecc33c
Compare
d938d19
to
693858d
Compare
This is finished, but I still have to untangle the various commits. |
693858d
to
6f26336
Compare
Commits untangled. |
6f26336
to
645098d
Compare
Rebased. |
645098d
to
22dc19d
Compare
Ready for review. |
Ah, the problem is Github lists commits in the wrong order (by timestamp), but merge wise |
Oh wow that is interesting. I last rebased two days ago. |
// Check that the data pointer is valid and that length times | ||
// item size is still inside the range. | ||
Whiskers templ(R"({ | ||
if gt(ptr, 0x100000000) { revert(0, 0) } |
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.
Is this a random constant (we assume it is not possible to transfer that much due to block gas limits)?
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
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.
Do you want something to be changed here?
8a98324
to
7adadfa
Compare
|
||
if (m_kind == Kind::External || m_kind == Kind::CallCode || m_kind == Kind::DelegateCall) | ||
for (auto& param: returnParameterTypes) | ||
if (param->isDynamicallySized() && !param->dataStoredIn(DataLocation::Storage)) |
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.
Can an external call return a storage pointer?
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, but only via delegatecall.
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.e. only a call to a library function.
|
||
bool dynamicReturnSize = false; | ||
for (auto const& retType: returnTypes) | ||
if (retType->isDynamicallyEncoded()) |
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.
Don't we have calldataEncodedSize
and isDynamicallyEncoded
on the TupleType
, do we need to iterate?
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.
Apparently no, but would it make sense to do so?
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.
Tuples are not fully-fledged types in Solidity, so I'm not sure which implications this would have.
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.
Let's postpone it. Created issue #3769.
else | ||
m_context << Instruction::POP; | ||
solAssert(retSize > 0, ""); | ||
m_context << (haveReturndatacopy ? eth::AssemblyItem(Instruction::RETURNDATASIZE) : u256(retSize)); |
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.
Why not just move this into the two parts of the if?
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 guess it is a separate step to always use returndatacopy and not allocate the memory on call.
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'll add a comment here stating:
Always use the actual return length, and not our calculated expected length, if returndatacopy is supported. This ensures it can catch badly formatted input from external calls.
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 was the idea, always use returndatacopy to detect badly formatted return data. Yes, please add the 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.
Actually I think this may warrant its own changelog entry as we're changing behaviour.
Compiling for byzantium (which is the default) may result in a new contract not working with an old one, if we had a case of invalid short encoding, or if the other one isn't Solidity and doesn't encode properly.
Unlikely, but still.
4683f91
to
7c3de57
Compare
/// From memory if @a _fromMemory is true, otherwise from call data. | ||
/// Calls revert if @a _revertOnOutOfBounds is true and the supplied size is shorter | ||
/// than the static data requirements or if dynamic data pointers reach outside of the | ||
/// area. Also has a hard cap of 0x100000000 for any given length/offset field. |
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.
@chriseth added this comment also
Fixes #3270
Fixes #2964
Fixes #3273
Fixes #3516
Depends on #3569