All
All
The best blockchain explorer of TRON
| Bug Name | Description | Severity |
|---|
Bug Name | Description | Severity |
LostStorageArrayWriteOnSlotOverflow Operations that involve clearing or copying from arrays that straddle the end of storage could result in silent data retention. | Solidity makes it possible to define variables that extend past the last (2**256-th) slot of storage, which results in wrap-around back to slot zero. Since EVM uses 256-bit integer arithmetic, most operations on such variables just work. The only situation which requires special attention is iteration against absolute slot addresses: the invariant that the last slot belonging to a variable has the highest address does not hold. When implemented incorrectly, a loop over an array will immediately terminate if the container spans the end of storage - due to the initial position already being greater than the end position. This affected storage array clearing loops generated by both evmasm and IR pipelines. Additionally, (only in the evmasm pipeline) copying operations whose source was an array straddling the end of storage were also affected. At the language level, the buggy code would be generated for array assignment, array initialization, delete operator, <array>.pop() and <array>.push(). Note that a clearing loop is inserted by the compiler not only for invocations of the delete operator, but also to zero storage when overwriting a longer array with a shorter one, popping an element or even pushing an empty element to a dynamic array. Since clearing is a separate loop, it is possible for the bug to only affect it and not the copy operation it follows (which is always the case in the IR pipeline). The bug is extremely unlikely to be triggered accidentally due to the probabilistic impossibility of a short dynamic array being allocated right at the storage boundary. On the other hand, scenarios in which a user may place a static array there intentionally do not seem realistic and are limited to unusual layouts, in which a contract does not place any storage variables at slot zero (otherwise they would overlap the array). | low |
DirtyBytesArrayToStorage Copying ``bytes`` arrays from memory or calldata to storage may result in dirty storage values. | Copying ``bytes`` arrays from memory or calldata to storage is done in chunks of 32 bytes even if the length is not a multiple of 32. Thereby, extra bytes past the end of the array may be copied from calldata or memory to storage. These dirty bytes may then become observable after a ``.push()`` without arguments to the bytes array in storage, i.e. such a push will not result in a zero value at the end of the array as expected. This bug only affects the legacy code generation pipeline, the new code generation pipeline via IR is not affected. | low |
ABIDecodeTwoDimensionalArrayMemory If used on memory byte arrays, result of the function ``abi.decode`` can depend on the contents of memory outside of the actual byte array that is decoded. | The ABI specification uses pointers to data areas for everything that is dynamically-sized. When decoding data from memory (instead of calldata), the ABI decoder did not properly validate some of these pointers. More specifically, it was possible to use large values for the pointers inside arrays such that computing the offset resulted in an undetected overflow. This could lead to these pointers targeting areas in memory outside of the actual area to be decoded. This way, it was possible for ``abi.decode`` to return different values for the same encoded byte array. | very low |
KeccakCaching The bytecode optimizer incorrectly reused previously evaluated Keccak-256 hashes. You are unlikely to be affected if you do not compute Keccak-256 hashes in inline assembly. | Solidity's bytecode optimizer has a step that can compute Keccak-256 hashes, if the contents of the memory are known during compilation time. This step also has a mechanism to determine that two Keccak-256 hashes are equal even if the values in memory are not known during compile time. This mechanism had a bug where Keccak-256 of the same memory content, but different sizes were considered equal. More specifically, ``keccak256(mpos1, length1)`` and ``keccak256(mpos2, length2)`` in some cases were considered equal if ``length1`` and ``length2``, when rounded up to nearest multiple of 32 were the same, and when the memory contents at ``mpos1`` and ``mpos2`` can be deduced to be equal. You maybe affected if you compute multiple Keccak-256 hashes of the same content, but with different lengths inside inline assembly. You are unaffected if your code uses ``keccak256`` with a length that is not a compile-time constant or if it is always a multiple of 32. | medium |
EmptyByteArrayCopy Copying an empty byte array (or string) from memory or calldata to storage can result in data corruption if the target array's length is increased subsequently without storing new data. | The routine that copies byte arrays from memory or calldata to storage stores unrelated data from after the source array in the storage slot if the source array is empty. If the storage array's length is subsequently increased either by using ``.push()`` or by assigning to its ``.length`` attribute (only before 0.6.0), the newly created byte array elements will not be zero-initialized, but contain the unrelated data. You are not affected if you do not assign to ``.length`` and do not use ``.push()`` on byte arrays, or only use ``.push(<arg>)`` or manually initialize the new elements. | medium |
DynamicArrayCleanup When assigning a dynamically-sized array with types of size at most 16 bytes in storage causing the assigned array to shrink, some parts of deleted slots were not zeroed out. | Consider a dynamically-sized array in storage whose base-type is small enough such that multiple values can be packed into a single slot, such as `uint128[]`. Let us define its length to be `l`. When this array gets assigned from another array with a smaller length, say `m`, the slots between elements `m` and `l` have to be cleaned by zeroing them out. However, this cleaning was not performed properly. Specifically, after the slot corresponding to `m`, only the first packed value was cleaned up. If this array gets resized to a length larger than `m`, the indices corresponding to the unclean parts of the slot contained the original value, instead of 0. The resizing here is performed by assigning to the array `length`, by a `push()` or via inline assembly. You are not affected if you are only using `.push(<arg>)` or if you assign a value (even zero) to the new elements after increasing the length of the array. | medium |
ImplicitConstructorCallvalueCheck The creation code of a contract that does not define a constructor but has a base that does define a constructor did not revert for calls with non-zero value. | Starting from Solidity 0.4.5 the creation code of contracts without explicit payable constructor is supposed to contain a callvalue check that results in contract creation reverting, if non-zero value is passed. However, this check was missing in case no explicit constructor was defined in a contract at all, but the contract has a base that does define a constructor. In these cases it is possible to send value in a contract creation transaction or using inline assembly without revert, even though the creation code is supposed to be non-payable. | very low |
TupleAssignmentMultiStackSlotComponents Tuple assignments with components that occupy several stack slots, i.e. nested tuples, pointers to external functions or references to dynamically sized calldata arrays, can result in invalid values. | Tuple assignments did not correctly account for tuple components that occupy multiple stack slots in case the number of stack slots differs between left-hand-side and right-hand-side. This can either happen in the presence of nested tuples or if the right-hand-side contains external function pointers or references to dynamic calldata arrays, while the left-hand-side contains an omission. | very low |
MemoryArrayCreationOverflow The creation of very large memory arrays can result in overlapping memory regions and thus memory corruption. | No runtime overflow checks were performed for the length of memory arrays during creation. In cases for which the memory size of an array in bytes, i.e. the array length times 32, is larger than 2^256-1, the memory allocation will overflow, potentially resulting in overlapping memory areas. The length of the array is still stored correctly, so copying or iterating over such an array will result in out-of-gas. | low |
privateCanBeOverridden Private methods can be overridden by inheriting contracts. | While private methods of base contracts are not visible and cannot be called directly from the derived contract, it is still possible to declare a function of the same name and type and thus change the behaviour of the base contract's function. | low |
SignedArrayStorageCopy Assigning an array of signed integers to a storage array of different type can lead to data corruption in that array. | In two's complement, negative integers have their higher order bits set. In order to fit into a shared storage slot, these have to be set to zero. When a conversion is done at the same time, the bits to set to zero were incorrectly determined from the source and not the target type. This means that such copy operations can lead to incorrect values being stored. | low/medium |
ABIEncoderV2StorageArrayWithMultiSlotElement Storage arrays containing structs or other statically-sized arrays are not read properly when directly encoded in external function calls or in abi.encode*. | When storage arrays whose elements occupy more than a single storage slot are directly encoded in external function calls or using abi.encode*, their elements are read in an overlapping manner, i.e. the element pointer is not properly advanced between reads. This is not a problem when the storage data is first copied to a memory variable or if the storage array only contains value types or dynamically-sized arrays. | low |
DynamicConstructorArgumentsClippedABIV2 A contract's constructor that takes structs or arrays that contain dynamically-sized arrays reverts or decodes to invalid data. | During construction of a contract, constructor parameters are copied from the code section to memory for decoding. The amount of bytes to copy was calculated incorrectly in case all parameters are statically-sized but contain dynamically-sized arrays as struct members or inner arrays. Such types are only available if ABIEncoderV2 is activated. | very low |
UninitializedFunctionPointerInConstructor Calling uninitialized internal function pointers created in the constructor does not always revert and can cause unexpected behaviour. | Uninitialized internal function pointers point to a special piece of code that causes a revert when called. Jump target positions are different during construction and after deployment, but the code for setting this special jump target only considered the situation after deployment. | very low |
IncorrectEventSignatureInLibraries Contract types used in events in libraries cause an incorrect event signature hash | Instead of using the type `address` in the hashed signature, the actual contract name was used, leading to a wrong hash in the logs. | very low |
ABIEncoderV2PackedStorage Storage structs and arrays with types shorter than 32 bytes can cause data corruption if encoded directly from storage using the experimental ABIEncoderV2. | Elements of structs and arrays that are shorter than 32 bytes are not properly decoded from storage when encoded directly (i.e. not via a memory type) using ABIEncoderV2. This can cause corruption in the values themselves but can also overwrite other parts of the encoded data. | low |