Solidity optimizer and abiencodev2 bug announcement
Thanks to the Ethereum Bug Bounty program, we have received a report on a flaw within the new experimental encoder ABI (called Abiencoderv2). During the survey, it was found that the component suffers from a few different variations of the same type. The first part of this announcement explains this bug in detail. The new Abi encoder is always marked as an experimental, but we nevertheless think that this deserves a prominent announcement because it is already used on Mainnet.
In addition, two low impact buses in the optimizer have been identified in the past two weeks, one of which has been corrected with Solidey v0.5.6. The two were introduced with version 0.5.5. See the second part of this ad for more details.
THE 0.5.7 Liberation Contains the fixes to all the bugs explained in this blog article.
All the bugs mentioned here must be easily visible in the tests that affect the relevant code paths, at least when they run with all the combinations of zero and non -zero values.
Credits to the Melonport team (Travis Jacobs and Jenna Zenk) and the Melon Council (Nick Munoz-McDonald, Martin Lundfall, Matt Di Ferrante and Adam Kolar), who reported it via the Bug Ethereum bonus program!
Which should be concerned
If you have deployed contracts that use the V2 experimental coder, they could be assigned. This means that only contracts that use the following directive in the source code can be assigned:
pragma experimental ABIEncoderV2;
In addition, there are a number of requirements for the bug to trigger. See the technical details below for more information.
As far as we can, there are around 2,500 live contracts on Mainnet which use experimental abiencodev2. It is not clear how many of them contain the bug.
How to check if the contract is vulnerable
The bug only manifests itself when all the following conditions are met:
- The storage data involving tables or structures are sent directly to an external function call, for Abi.Ecode or to the event data without prior assignment to a local variable (memory) and
- There is a table that contains elements with a size less than 32 bytes or a structure that has elements that share a storage slit or members of the type Bytesnn less than 32 bytes.
In addition to that, in the following situations, your code is not affected:
- If all your structures or tables only use Uint256 Or Int256 guys
- If you only use whole types (this may be shorter) and you only code at a table at a time
- If you only return this data and do not use it in Abi.EcodeExternal calls or event data.
If you have a contract that meets these conditions and want to check if the contract is actually vulnerable, you can contact us via Security@ethereum.org.
How to prevent these types of defects in the future
In order to be conservative about changes, the experimental abi encoder was only available when he is explicitly activated, to allow people to interact with him and test it without putting too much confidence before he is not considered stable.
We do our best to ensure high quality and we have recently started working on the “semantic” fuzzage of certain pieces on Oss-fuzz (We previously compiled the compiler, but that did not test the accuracy of the compiler).
For developers – Solidity compiler bugs are difficult to detect with tools such as vulnerability detectors, because the tools that work on source code or AST representations do not detect defects that are only introduced in the compilé bytecode .
The best way to protect yourself from these types of defects is to have a rigorous set of end -to -end tests for your contracts (verification of all code paths), because the compiler bugs are most likely ” silent “and manifest themselves rather in invalid data.
Possible consequences
Naturally, any bug can have variable consequences depending on the program control flow, but we expect it to be more likely to lead to dysfunction than to exploitability.
The bug, when triggered, in certain circumstances, will send corrupt parameters on the invocations of the method to other contracts.
Chronology
2019-03-16:
- Report via Bug Bounty, about corruption caused when reading Boolean tables directly from storage in an abi encoder.
2019-03-16 to 2019-03-21:
- Investigation of the deep cause, analysis of affected contracts. A number of contracts compiled unexpectedly compiled with the experimental coder was found deployed on Mainnet, many of which without verified source code.
- The survey on the bug found more ways to trigger the bug, for example using structures. In addition, a table overflow bug was found in the same routine.
- A handful of contracts found on GitHub were verified and none have been deemed affected.
- A bugfix of the Abi encoder was made.
2019-03-20:
- Decision to make information public.
- Reasoning: It would not be possible to detect all vulnerable contracts and to contact all the authors in a timely manner, and it would be good to prevent an additional proliferation of vulnerable contracts on the advantage.
2019-03-26:
- New version of the compiler, version 0.5.7.
- This message is published.
Technical details
Background
The ABI contract is a specification how the data can be exchanged with outside contracts (A DAPP) or during the interaction between contracts. It supports a variety of data types, including simple values such as numbers, bytes and chains, as well as more complex data, including tables and structures.
When a contract receives entry data, he must decode that (this is done by the “Decoder Abi”) and before returning data or sending data to another contract, he must code it (this is made by the “abi encoder”). The solidity compiler generates these two documents of code for each function defined in a contract (and also for Abi.Ecode And Abi.Decode). In the solidity compiler, the subsystem generating the coder and the decoder is called “abi encoder”.
In mid-2017, the Solidity team began working on a new implementation called “Abi encode V2” in order to have a more flexible, safe, efficient and auditable code generator. This experimental code generator, when explicitly activated, has been offered to users since the end of 2017 with version 0.4.19.
The flaw
The experimental abi coder does not properly manage the non -whole values of 32 bytes. This applies to Bytesnn types, Bool,, list And other types when they are part of a table or structure and coded directly from storage. This means that these storage references should be used directly inside Abi.Ecode (…)as arguments in external function calls or in event data without prior assignment to a local variable. Using back Do not trigger the bug. The guys Bytesnn And Bool will result in corrupt data while list could lead to an invalid to come back.
In addition, tables with shorter elements than 32 bytes may not be managed correctly even if the basic type is an integer type. The encoding of these tables in the manner described above can cause other data in the crushed coding if the number of coded elements is not a multiple of the number of elements that adapt to a single slit. If nothing follows the table in the coding (note that the dynamic size tables are always coded after static size tables with static size content), or if only one table is coded, no other data is crushed.
Not linked to the problem of the ability to be explained above, two bugs were found in optimization. The two were introduced with 0.5.5 (released on March 5). It is unlikely that they will occur in the code generated by the compiler, unless online assembly is used.
These two bugs were identified by the recent addition of Solidey Oss-fuzz – A safety tool box to find differences or problems in a variety of projects. For solidity, we have included several different fuzzers testing different aspects of the compiler.
- The optimizer transforms Opcode sequences as (((x <<<) << b))Or A And B are compilation-time constants, in (x <<< (a + b)) While not correctly manipulating the overflow in the addition.
- The optimizer incorrectly manages the byte OPCODE If Constant 31 is used as the second argument. This can occur when execution of access to the index on Bytesnn Types with a constant compilation time value (not index) of 31 or when using the byte opcode in online assembly.
This message was composed jointly by @Axic, @chriseth, @Holiman