Merge pull request #13045 from ethereum/bytesArrayToStorageBug

Bytes array to storage bug
This commit is contained in:
Daniel Kirchner 2022-06-15 10:21:01 +02:00 committed by GitHub
commit b45bc3918f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 238 additions and 136 deletions

View File

@ -1,6 +1,7 @@
### 0.8.15 (unreleased)
Important Bugfixes:
* Code Generation: Avoid writing dirty bytes to storage when copying ``bytes`` arrays.
* Yul Optimizer: Keep all memory side-effects of inline assembly blocks.

View File

@ -1,4 +1,14 @@
[
{
"uid": "SOL-2022-5",
"name": "DirtyBytesArrayToStorage",
"summary": "Copying ``bytes`` arrays from memory or calldata to storage may result in dirty storage values.",
"description": "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.",
"link": "https://blog.soliditylang.org/2022/06/15/dirty-bytes-array-to-storage-bug/",
"introduced": "0.0.1",
"fixed": "0.8.15",
"severity": "low"
},
{
"uid": "SOL-2022-4",
"name": "InlineAssemblyMemorySideEffects",

View File

@ -1,6 +1,7 @@
{
"0.1.0": {
"bugs": [
"DirtyBytesArrayToStorage",
"KeccakCaching",
"EmptyByteArrayCopy",
"DynamicArrayCleanup",
@ -22,6 +23,7 @@
},
"0.1.1": {
"bugs": [
"DirtyBytesArrayToStorage",
"KeccakCaching",
"EmptyByteArrayCopy",
"DynamicArrayCleanup",
@ -43,6 +45,7 @@
},
"0.1.2": {
"bugs": [
"DirtyBytesArrayToStorage",
"KeccakCaching",
"EmptyByteArrayCopy",
"DynamicArrayCleanup",
@ -64,6 +67,7 @@
},
"0.1.3": {
"bugs": [
"DirtyBytesArrayToStorage",
"KeccakCaching",
"EmptyByteArrayCopy",
"DynamicArrayCleanup",
@ -85,6 +89,7 @@
},
"0.1.4": {
"bugs": [
"DirtyBytesArrayToStorage",
"KeccakCaching",
"EmptyByteArrayCopy",
"DynamicArrayCleanup",
@ -107,6 +112,7 @@
},
"0.1.5": {
"bugs": [
"DirtyBytesArrayToStorage",
"KeccakCaching",
"EmptyByteArrayCopy",
"DynamicArrayCleanup",
@ -129,6 +135,7 @@
},
"0.1.6": {
"bugs": [
"DirtyBytesArrayToStorage",
"KeccakCaching",
"EmptyByteArrayCopy",
"DynamicArrayCleanup",
@ -153,6 +160,7 @@
},
"0.1.7": {
"bugs": [
"DirtyBytesArrayToStorage",
"KeccakCaching",
"EmptyByteArrayCopy",
"DynamicArrayCleanup",
@ -177,6 +185,7 @@
},
"0.2.0": {
"bugs": [
"DirtyBytesArrayToStorage",
"KeccakCaching",
"EmptyByteArrayCopy",
"DynamicArrayCleanup",
@ -202,6 +211,7 @@
},
"0.2.1": {
"bugs": [
"DirtyBytesArrayToStorage",
"KeccakCaching",
"EmptyByteArrayCopy",
"DynamicArrayCleanup",
@ -227,6 +237,7 @@
},
"0.2.2": {
"bugs": [
"DirtyBytesArrayToStorage",
"KeccakCaching",
"EmptyByteArrayCopy",
"DynamicArrayCleanup",
@ -252,6 +263,7 @@
},
"0.3.0": {
"bugs": [
"DirtyBytesArrayToStorage",
"KeccakCaching",
"EmptyByteArrayCopy",
"DynamicArrayCleanup",
@ -279,6 +291,7 @@
},
"0.3.1": {
"bugs": [
"DirtyBytesArrayToStorage",
"KeccakCaching",
"EmptyByteArrayCopy",
"DynamicArrayCleanup",
@ -305,6 +318,7 @@
},
"0.3.2": {
"bugs": [
"DirtyBytesArrayToStorage",
"KeccakCaching",
"EmptyByteArrayCopy",
"DynamicArrayCleanup",
@ -331,6 +345,7 @@
},
"0.3.3": {
"bugs": [
"DirtyBytesArrayToStorage",
"KeccakCaching",
"EmptyByteArrayCopy",
"DynamicArrayCleanup",
@ -356,6 +371,7 @@
},
"0.3.4": {
"bugs": [
"DirtyBytesArrayToStorage",
"KeccakCaching",
"EmptyByteArrayCopy",
"DynamicArrayCleanup",
@ -381,6 +397,7 @@
},
"0.3.5": {
"bugs": [
"DirtyBytesArrayToStorage",
"KeccakCaching",
"EmptyByteArrayCopy",
"DynamicArrayCleanup",
@ -406,6 +423,7 @@
},
"0.3.6": {
"bugs": [
"DirtyBytesArrayToStorage",
"KeccakCaching",
"EmptyByteArrayCopy",
"DynamicArrayCleanup",
@ -429,6 +447,7 @@
},
"0.4.0": {
"bugs": [
"DirtyBytesArrayToStorage",
"KeccakCaching",
"EmptyByteArrayCopy",
"DynamicArrayCleanup",
@ -452,6 +471,7 @@
},
"0.4.1": {
"bugs": [
"DirtyBytesArrayToStorage",
"KeccakCaching",
"EmptyByteArrayCopy",
"DynamicArrayCleanup",
@ -475,6 +495,7 @@
},
"0.4.10": {
"bugs": [
"DirtyBytesArrayToStorage",
"KeccakCaching",
"EmptyByteArrayCopy",
"DynamicArrayCleanup",
@ -497,6 +518,7 @@
},
"0.4.11": {
"bugs": [
"DirtyBytesArrayToStorage",
"KeccakCaching",
"EmptyByteArrayCopy",
"DynamicArrayCleanup",
@ -518,6 +540,7 @@
},
"0.4.12": {
"bugs": [
"DirtyBytesArrayToStorage",
"KeccakCaching",
"EmptyByteArrayCopy",
"DynamicArrayCleanup",
@ -538,6 +561,7 @@
},
"0.4.13": {
"bugs": [
"DirtyBytesArrayToStorage",
"KeccakCaching",
"EmptyByteArrayCopy",
"DynamicArrayCleanup",
@ -558,6 +582,7 @@
},
"0.4.14": {
"bugs": [
"DirtyBytesArrayToStorage",
"KeccakCaching",
"EmptyByteArrayCopy",
"DynamicArrayCleanup",
@ -577,6 +602,7 @@
},
"0.4.15": {
"bugs": [
"DirtyBytesArrayToStorage",
"KeccakCaching",
"EmptyByteArrayCopy",
"DynamicArrayCleanup",
@ -595,6 +621,7 @@
},
"0.4.16": {
"bugs": [
"DirtyBytesArrayToStorage",
"ABIDecodeTwoDimensionalArrayMemory",
"KeccakCaching",
"EmptyByteArrayCopy",
@ -616,6 +643,7 @@
},
"0.4.17": {
"bugs": [
"DirtyBytesArrayToStorage",
"ABIDecodeTwoDimensionalArrayMemory",
"KeccakCaching",
"EmptyByteArrayCopy",
@ -638,6 +666,7 @@
},
"0.4.18": {
"bugs": [
"DirtyBytesArrayToStorage",
"ABIDecodeTwoDimensionalArrayMemory",
"KeccakCaching",
"EmptyByteArrayCopy",
@ -659,6 +688,7 @@
},
"0.4.19": {
"bugs": [
"DirtyBytesArrayToStorage",
"ABIDecodeTwoDimensionalArrayMemory",
"KeccakCaching",
"EmptyByteArrayCopy",
@ -681,6 +711,7 @@
},
"0.4.2": {
"bugs": [
"DirtyBytesArrayToStorage",
"KeccakCaching",
"EmptyByteArrayCopy",
"DynamicArrayCleanup",
@ -703,6 +734,7 @@
},
"0.4.20": {
"bugs": [
"DirtyBytesArrayToStorage",
"ABIDecodeTwoDimensionalArrayMemory",
"KeccakCaching",
"EmptyByteArrayCopy",
@ -725,6 +757,7 @@
},
"0.4.21": {
"bugs": [
"DirtyBytesArrayToStorage",
"ABIDecodeTwoDimensionalArrayMemory",
"KeccakCaching",
"EmptyByteArrayCopy",
@ -747,6 +780,7 @@
},
"0.4.22": {
"bugs": [
"DirtyBytesArrayToStorage",
"ABIDecodeTwoDimensionalArrayMemory",
"KeccakCaching",
"EmptyByteArrayCopy",
@ -769,6 +803,7 @@
},
"0.4.23": {
"bugs": [
"DirtyBytesArrayToStorage",
"ABIDecodeTwoDimensionalArrayMemory",
"KeccakCaching",
"EmptyByteArrayCopy",
@ -790,6 +825,7 @@
},
"0.4.24": {
"bugs": [
"DirtyBytesArrayToStorage",
"ABIDecodeTwoDimensionalArrayMemory",
"KeccakCaching",
"EmptyByteArrayCopy",
@ -811,6 +847,7 @@
},
"0.4.25": {
"bugs": [
"DirtyBytesArrayToStorage",
"ABIDecodeTwoDimensionalArrayMemory",
"KeccakCaching",
"EmptyByteArrayCopy",
@ -830,6 +867,7 @@
},
"0.4.26": {
"bugs": [
"DirtyBytesArrayToStorage",
"ABIDecodeTwoDimensionalArrayMemory",
"KeccakCaching",
"EmptyByteArrayCopy",
@ -846,6 +884,7 @@
},
"0.4.3": {
"bugs": [
"DirtyBytesArrayToStorage",
"KeccakCaching",
"EmptyByteArrayCopy",
"DynamicArrayCleanup",
@ -867,6 +906,7 @@
},
"0.4.4": {
"bugs": [
"DirtyBytesArrayToStorage",
"KeccakCaching",
"EmptyByteArrayCopy",
"DynamicArrayCleanup",
@ -887,6 +927,7 @@
},
"0.4.5": {
"bugs": [
"DirtyBytesArrayToStorage",
"KeccakCaching",
"EmptyByteArrayCopy",
"DynamicArrayCleanup",
@ -910,6 +951,7 @@
},
"0.4.6": {
"bugs": [
"DirtyBytesArrayToStorage",
"KeccakCaching",
"EmptyByteArrayCopy",
"DynamicArrayCleanup",
@ -932,6 +974,7 @@
},
"0.4.7": {
"bugs": [
"DirtyBytesArrayToStorage",
"KeccakCaching",
"EmptyByteArrayCopy",
"DynamicArrayCleanup",
@ -954,6 +997,7 @@
},
"0.4.8": {
"bugs": [
"DirtyBytesArrayToStorage",
"KeccakCaching",
"EmptyByteArrayCopy",
"DynamicArrayCleanup",
@ -976,6 +1020,7 @@
},
"0.4.9": {
"bugs": [
"DirtyBytesArrayToStorage",
"KeccakCaching",
"EmptyByteArrayCopy",
"DynamicArrayCleanup",
@ -998,6 +1043,7 @@
},
"0.5.0": {
"bugs": [
"DirtyBytesArrayToStorage",
"ABIDecodeTwoDimensionalArrayMemory",
"KeccakCaching",
"EmptyByteArrayCopy",
@ -1017,6 +1063,7 @@
},
"0.5.1": {
"bugs": [
"DirtyBytesArrayToStorage",
"ABIDecodeTwoDimensionalArrayMemory",
"KeccakCaching",
"EmptyByteArrayCopy",
@ -1036,6 +1083,7 @@
},
"0.5.10": {
"bugs": [
"DirtyBytesArrayToStorage",
"NestedCallataArrayAbiReencodingSizeValidation",
"ABIDecodeTwoDimensionalArrayMemory",
"KeccakCaching",
@ -1052,6 +1100,7 @@
},
"0.5.11": {
"bugs": [
"DirtyBytesArrayToStorage",
"NestedCallataArrayAbiReencodingSizeValidation",
"ABIDecodeTwoDimensionalArrayMemory",
"KeccakCaching",
@ -1067,6 +1116,7 @@
},
"0.5.12": {
"bugs": [
"DirtyBytesArrayToStorage",
"NestedCallataArrayAbiReencodingSizeValidation",
"ABIDecodeTwoDimensionalArrayMemory",
"KeccakCaching",
@ -1082,6 +1132,7 @@
},
"0.5.13": {
"bugs": [
"DirtyBytesArrayToStorage",
"NestedCallataArrayAbiReencodingSizeValidation",
"ABIDecodeTwoDimensionalArrayMemory",
"KeccakCaching",
@ -1097,6 +1148,7 @@
},
"0.5.14": {
"bugs": [
"DirtyBytesArrayToStorage",
"NestedCallataArrayAbiReencodingSizeValidation",
"ABIDecodeTwoDimensionalArrayMemory",
"KeccakCaching",
@ -1114,6 +1166,7 @@
},
"0.5.15": {
"bugs": [
"DirtyBytesArrayToStorage",
"NestedCallataArrayAbiReencodingSizeValidation",
"ABIDecodeTwoDimensionalArrayMemory",
"KeccakCaching",
@ -1130,6 +1183,7 @@
},
"0.5.16": {
"bugs": [
"DirtyBytesArrayToStorage",
"NestedCallataArrayAbiReencodingSizeValidation",
"ABIDecodeTwoDimensionalArrayMemory",
"KeccakCaching",
@ -1145,6 +1199,7 @@
},
"0.5.17": {
"bugs": [
"DirtyBytesArrayToStorage",
"NestedCallataArrayAbiReencodingSizeValidation",
"ABIDecodeTwoDimensionalArrayMemory",
"KeccakCaching",
@ -1159,6 +1214,7 @@
},
"0.5.2": {
"bugs": [
"DirtyBytesArrayToStorage",
"ABIDecodeTwoDimensionalArrayMemory",
"KeccakCaching",
"EmptyByteArrayCopy",
@ -1178,6 +1234,7 @@
},
"0.5.3": {
"bugs": [
"DirtyBytesArrayToStorage",
"ABIDecodeTwoDimensionalArrayMemory",
"KeccakCaching",
"EmptyByteArrayCopy",
@ -1197,6 +1254,7 @@
},
"0.5.4": {
"bugs": [
"DirtyBytesArrayToStorage",
"ABIDecodeTwoDimensionalArrayMemory",
"KeccakCaching",
"EmptyByteArrayCopy",
@ -1216,6 +1274,7 @@
},
"0.5.5": {
"bugs": [
"DirtyBytesArrayToStorage",
"ABIDecodeTwoDimensionalArrayMemory",
"KeccakCaching",
"EmptyByteArrayCopy",
@ -1237,6 +1296,7 @@
},
"0.5.6": {
"bugs": [
"DirtyBytesArrayToStorage",
"ABIDecodeTwoDimensionalArrayMemory",
"KeccakCaching",
"EmptyByteArrayCopy",
@ -1258,6 +1318,7 @@
},
"0.5.7": {
"bugs": [
"DirtyBytesArrayToStorage",
"ABIDecodeTwoDimensionalArrayMemory",
"KeccakCaching",
"EmptyByteArrayCopy",
@ -1277,6 +1338,7 @@
},
"0.5.8": {
"bugs": [
"DirtyBytesArrayToStorage",
"NestedCallataArrayAbiReencodingSizeValidation",
"ABIDecodeTwoDimensionalArrayMemory",
"KeccakCaching",
@ -1296,6 +1358,7 @@
},
"0.5.9": {
"bugs": [
"DirtyBytesArrayToStorage",
"NestedCallataArrayAbiReencodingSizeValidation",
"ABIDecodeTwoDimensionalArrayMemory",
"KeccakCaching",
@ -1314,6 +1377,7 @@
},
"0.6.0": {
"bugs": [
"DirtyBytesArrayToStorage",
"NestedCallataArrayAbiReencodingSizeValidation",
"ABIDecodeTwoDimensionalArrayMemory",
"KeccakCaching",
@ -1330,6 +1394,7 @@
},
"0.6.1": {
"bugs": [
"DirtyBytesArrayToStorage",
"NestedCallataArrayAbiReencodingSizeValidation",
"ABIDecodeTwoDimensionalArrayMemory",
"KeccakCaching",
@ -1345,6 +1410,7 @@
},
"0.6.10": {
"bugs": [
"DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride",
"NestedCallataArrayAbiReencodingSizeValidation",
"SignedImmutables",
@ -1357,6 +1423,7 @@
},
"0.6.11": {
"bugs": [
"DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride",
"NestedCallataArrayAbiReencodingSizeValidation",
"SignedImmutables",
@ -1369,6 +1436,7 @@
},
"0.6.12": {
"bugs": [
"DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride",
"NestedCallataArrayAbiReencodingSizeValidation",
"SignedImmutables",
@ -1381,6 +1449,7 @@
},
"0.6.2": {
"bugs": [
"DirtyBytesArrayToStorage",
"NestedCallataArrayAbiReencodingSizeValidation",
"ABIDecodeTwoDimensionalArrayMemory",
"KeccakCaching",
@ -1396,6 +1465,7 @@
},
"0.6.3": {
"bugs": [
"DirtyBytesArrayToStorage",
"NestedCallataArrayAbiReencodingSizeValidation",
"ABIDecodeTwoDimensionalArrayMemory",
"KeccakCaching",
@ -1411,6 +1481,7 @@
},
"0.6.4": {
"bugs": [
"DirtyBytesArrayToStorage",
"NestedCallataArrayAbiReencodingSizeValidation",
"ABIDecodeTwoDimensionalArrayMemory",
"KeccakCaching",
@ -1426,6 +1497,7 @@
},
"0.6.5": {
"bugs": [
"DirtyBytesArrayToStorage",
"NestedCallataArrayAbiReencodingSizeValidation",
"SignedImmutables",
"ABIDecodeTwoDimensionalArrayMemory",
@ -1441,6 +1513,7 @@
},
"0.6.6": {
"bugs": [
"DirtyBytesArrayToStorage",
"NestedCallataArrayAbiReencodingSizeValidation",
"SignedImmutables",
"ABIDecodeTwoDimensionalArrayMemory",
@ -1455,6 +1528,7 @@
},
"0.6.7": {
"bugs": [
"DirtyBytesArrayToStorage",
"NestedCallataArrayAbiReencodingSizeValidation",
"SignedImmutables",
"ABIDecodeTwoDimensionalArrayMemory",
@ -1469,6 +1543,7 @@
},
"0.6.8": {
"bugs": [
"DirtyBytesArrayToStorage",
"NestedCallataArrayAbiReencodingSizeValidation",
"SignedImmutables",
"ABIDecodeTwoDimensionalArrayMemory",
@ -1480,6 +1555,7 @@
},
"0.6.9": {
"bugs": [
"DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride",
"NestedCallataArrayAbiReencodingSizeValidation",
"SignedImmutables",
@ -1493,6 +1569,7 @@
},
"0.7.0": {
"bugs": [
"DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride",
"NestedCallataArrayAbiReencodingSizeValidation",
"SignedImmutables",
@ -1505,6 +1582,7 @@
},
"0.7.1": {
"bugs": [
"DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride",
"NestedCallataArrayAbiReencodingSizeValidation",
"SignedImmutables",
@ -1518,6 +1596,7 @@
},
"0.7.2": {
"bugs": [
"DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride",
"NestedCallataArrayAbiReencodingSizeValidation",
"SignedImmutables",
@ -1530,6 +1609,7 @@
},
"0.7.3": {
"bugs": [
"DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride",
"NestedCallataArrayAbiReencodingSizeValidation",
"SignedImmutables",
@ -1541,6 +1621,7 @@
},
"0.7.4": {
"bugs": [
"DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride",
"NestedCallataArrayAbiReencodingSizeValidation",
"SignedImmutables",
@ -1551,6 +1632,7 @@
},
"0.7.5": {
"bugs": [
"DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride",
"NestedCallataArrayAbiReencodingSizeValidation",
"SignedImmutables",
@ -1561,6 +1643,7 @@
},
"0.7.6": {
"bugs": [
"DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride",
"NestedCallataArrayAbiReencodingSizeValidation",
"SignedImmutables",
@ -1571,6 +1654,7 @@
},
"0.8.0": {
"bugs": [
"DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride",
"NestedCallataArrayAbiReencodingSizeValidation",
"SignedImmutables",
@ -1581,6 +1665,7 @@
},
"0.8.1": {
"bugs": [
"DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride",
"NestedCallataArrayAbiReencodingSizeValidation",
"SignedImmutables",
@ -1591,6 +1676,7 @@
},
"0.8.10": {
"bugs": [
"DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride",
"NestedCallataArrayAbiReencodingSizeValidation"
],
@ -1598,6 +1684,7 @@
},
"0.8.11": {
"bugs": [
"DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride",
"NestedCallataArrayAbiReencodingSizeValidation",
"AbiEncodeCallLiteralAsFixedBytesBug"
@ -1606,6 +1693,7 @@
},
"0.8.12": {
"bugs": [
"DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride",
"NestedCallataArrayAbiReencodingSizeValidation",
"AbiEncodeCallLiteralAsFixedBytesBug"
@ -1614,6 +1702,7 @@
},
"0.8.13": {
"bugs": [
"DirtyBytesArrayToStorage",
"InlineAssemblyMemorySideEffects",
"DataLocationChangeInInternalOverride",
"NestedCallataArrayAbiReencodingSizeValidation"
@ -1622,12 +1711,14 @@
},
"0.8.14": {
"bugs": [
"DirtyBytesArrayToStorage",
"InlineAssemblyMemorySideEffects"
],
"released": "2022-05-17"
},
"0.8.2": {
"bugs": [
"DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride",
"NestedCallataArrayAbiReencodingSizeValidation",
"SignedImmutables",
@ -1638,6 +1729,7 @@
},
"0.8.3": {
"bugs": [
"DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride",
"NestedCallataArrayAbiReencodingSizeValidation",
"SignedImmutables",
@ -1647,6 +1739,7 @@
},
"0.8.4": {
"bugs": [
"DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride",
"NestedCallataArrayAbiReencodingSizeValidation",
"SignedImmutables"
@ -1655,6 +1748,7 @@
},
"0.8.5": {
"bugs": [
"DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride",
"NestedCallataArrayAbiReencodingSizeValidation",
"SignedImmutables"
@ -1663,6 +1757,7 @@
},
"0.8.6": {
"bugs": [
"DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride",
"NestedCallataArrayAbiReencodingSizeValidation",
"SignedImmutables"
@ -1671,6 +1766,7 @@
},
"0.8.7": {
"bugs": [
"DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride",
"NestedCallataArrayAbiReencodingSizeValidation",
"SignedImmutables"
@ -1679,6 +1775,7 @@
},
"0.8.8": {
"bugs": [
"DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride",
"NestedCallataArrayAbiReencodingSizeValidation",
"UserDefinedValueTypesBug",
@ -1688,6 +1785,7 @@
},
"0.8.9": {
"bugs": [
"DirtyBytesArrayToStorage",
"DataLocationChangeInInternalOverride",
"NestedCallataArrayAbiReencodingSizeValidation"
],

View File

@ -154,37 +154,6 @@ hiding new and different behavior in existing code.
- New code generator: ``0`` as all parameters, including return parameters, will be re-initialized before
each ``_;`` evaluation.
- Copying ``bytes`` arrays from memory to storage is implemented in a different way.
The old code generator always copies full words, while the new one cuts the byte
array after its end. The old behaviour can lead to dirty data being copied after
the end of the array (but still in the same storage slot).
This causes differences in some contracts, for example:
.. code-block:: solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.1;
contract C {
bytes x;
function f() public returns (uint r) {
bytes memory m = "tmp";
assembly {
mstore(m, 8)
mstore(add(m, 32), "deadbeef15dead")
}
x = m;
assembly {
r := sload(x.slot)
}
}
}
Previously ``f()`` would return ``0x6465616462656566313564656164000000000000000000000000000000000010``
(it has correct length, and correct first 8 elements, but then it contains dirty data which was set via assembly).
Now it is returning ``0x6465616462656566000000000000000000000000000000000000000000000010`` (it has
correct length, and correct elements, but does not contain superfluous data).
.. index:: ! evaluation order; expression
- For the old code generator, the evaluation order of expressions is unspecified.

View File

@ -50,9 +50,8 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
// stack layout: [source_ref] [source length] target_ref (top)
solAssert(_targetType.location() == DataLocation::Storage, "");
Type const* uint256 = TypeProvider::uint256();
Type const* targetBaseType = _targetType.isByteArrayOrString() ? uint256 : _targetType.baseType();
Type const* sourceBaseType = _sourceType.isByteArrayOrString() ? uint256 : _sourceType.baseType();
Type const* targetBaseType = _targetType.baseType();
Type const* sourceBaseType = _sourceType.baseType();
// TODO unroll loop for small sizes
@ -68,7 +67,38 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
for (unsigned i = _sourceType.sizeOnStack(); i > 0; --i)
m_context << swapInstruction(i);
// stack: target_ref source_ref [source_length]
// stack: target_ref source_ref [source_length]
if (_targetType.isByteArrayOrString())
{
// stack: target_ref source_ref [source_length]
if (fromCalldata && _sourceType.isDynamicallySized())
{
// stack: target_ref source_ref source_length
m_context << Instruction::SWAP1;
// stack: target_ref source_length source_ref
m_context << Instruction::DUP3;
// stack: target_ref source_length source_ref target_ref
m_context.callYulFunction(
m_context.utilFunctions().copyByteArrayToStorageFunction(_sourceType, _targetType),
3,
0
);
}
else
{
// stack: target_ref source_ref
m_context << Instruction::DUP2;
// stack: target_ref source_ref target_ref
m_context.callYulFunction(
m_context.utilFunctions().copyByteArrayToStorageFunction(_sourceType, _targetType),
2,
0
);
}
// stack: target_ref
return;
}
// retrieve source length
if (_sourceType.location() != DataLocation::CallData || !_sourceType.isDynamicallySized())
retrieveLength(_sourceType); // otherwise, length is already there
@ -97,10 +127,11 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
utils.retrieveLength(_targetType);
// stack: target_ref source_ref source_length target_ref target_length
if (_targetType.isDynamicallySized())
{
// store new target length
if (!_targetType.isByteArrayOrString())
// Otherwise, length will be stored below.
_context << Instruction::DUP3 << Instruction::DUP3 << Instruction::SSTORE;
solAssert(!_targetType.isByteArrayOrString());
_context << Instruction::DUP3 << Instruction::DUP3 << Instruction::SSTORE;
}
if (sourceBaseType->category() == Type::Category::Mapping)
{
solAssert(targetBaseType->category() == Type::Category::Mapping, "");
@ -125,51 +156,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
// stack: target_ref target_data_end source_length target_data_pos source_ref
evmasm::AssemblyItem copyLoopEndWithoutByteOffset = _context.newTag();
// special case for short byte arrays: Store them together with their length.
if (_targetType.isByteArrayOrString())
{
// stack: target_ref target_data_end source_length target_data_pos source_ref
_context << Instruction::DUP3;
evmasm::AssemblyItem nonEmptyByteArray = _context.appendConditionalJump();
// Empty source, just zero out the main slot.
_context << u256(0) << Instruction::DUP6 << Instruction::SSTORE;
_context.appendJumpTo(copyLoopEndWithoutByteOffset);
_context << nonEmptyByteArray;
// Non-empty source.
// stack: target_ref target_data_end source_length target_data_pos source_ref
_context << Instruction::DUP3 << u256(31) << Instruction::LT;
evmasm::AssemblyItem longByteArray = _context.appendConditionalJump();
// store the short byte array
solAssert(_sourceType.isByteArrayOrString(), "");
if (_sourceType.location() == DataLocation::Storage)
{
// just copy the slot, it contains length and data
_context << Instruction::DUP1 << Instruction::SLOAD;
_context << Instruction::DUP6 << Instruction::SSTORE;
}
else
{
_context << Instruction::DUP1;
CompilerUtils(_context).loadFromMemoryDynamic(*sourceBaseType, fromCalldata, true, false);
// stack: target_ref target_data_end source_length target_data_pos source_ref value
// clear the lower-order byte - which will hold the length
_context << u256(0xff) << Instruction::NOT << Instruction::AND;
// fetch the length and shift it left by one
_context << Instruction::DUP4 << Instruction::DUP1 << Instruction::ADD;
// combine value and length and store them
_context << Instruction::OR << Instruction::DUP6 << Instruction::SSTORE;
}
// end of special case, jump right into cleaning target data area
_context.appendJumpTo(copyLoopEndWithoutByteOffset);
_context << longByteArray;
// Store length (2*length+1)
_context << Instruction::DUP3 << Instruction::DUP1 << Instruction::ADD;
_context << u256(1) << Instruction::ADD;
_context << Instruction::DUP6 << Instruction::SSTORE;
}
solAssert(!_targetType.isByteArrayOrString());
// skip copying if source length is zero
_context << Instruction::DUP3 << Instruction::ISZERO;
_context.appendConditionalJumpTo(copyLoopEndWithoutByteOffset);

View File

@ -23,5 +23,5 @@ contract C {
// ----
// f() -> 0x20, 0x8, 0x40, 0x3, 0x9, 0xa, 0xb
// gas irOptimized: 203172
// gas legacy: 206075
// gas legacyOptimized: 203059
// gas legacy: 206343
// gas legacyOptimized: 203162

View File

@ -10,5 +10,5 @@ contract C {
// ----
// f(bytes): 0x20, 0x80, 0x21, 0x40, 0x7, "abcdefg" -> 0x21, 0x40, 0x7, "abcdefg"
// gas irOptimized: 135787
// gas legacy: 137181
// gas legacyOptimized: 136073
// gas legacy: 137377
// gas legacyOptimized: 136125

View File

@ -14,6 +14,6 @@ contract c {
// getLength() -> 0
// set(): 1, 2 -> true
// gas irOptimized: 110402
// gas legacy: 110723
// gas legacyOptimized: 110564
// gas legacy: 110968
// gas legacyOptimized: 110585
// getLength() -> 68

View File

@ -6,12 +6,12 @@ contract c {
// ----
// set(uint256): 1, 2 -> true
// gas irOptimized: 110576
// gas legacy: 111088
// gas legacyOptimized: 110733
// gas legacy: 111333
// gas legacyOptimized: 110750
// set(uint256): 2, 2, 3, 4, 5 -> true
// gas irOptimized: 177527
// gas legacy: 178018
// gas legacyOptimized: 177663
// gas legacy: 178335
// gas legacyOptimized: 177725
// storageEmpty -> 0
// copy(uint256,uint256): 1, 2 -> true
// storageEmpty -> 0

View File

@ -18,24 +18,24 @@ contract c {
// f(uint256): 0 -> 0x20, 0x00
// f(uint256): 31 -> 0x20, 0x1f, 0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e00
// gas irOptimized: 108395
// gas legacy: 123884
// gas legacyOptimized: 119139
// gas legacy: 124322
// gas legacyOptimized: 119141
// f(uint256): 32 -> 0x20, 0x20, 1780731860627700044960722568376592200742329637303199754547598369979440671
// gas irOptimized: 117480
// gas legacy: 134936
// gas legacyOptimized: 130046
// gas legacy: 135259
// gas legacyOptimized: 130089
// f(uint256): 33 -> 0x20, 33, 1780731860627700044960722568376592200742329637303199754547598369979440671, 0x2000000000000000000000000000000000000000000000000000000000000000
// gas irOptimized: 124117
// gas legacy: 141728
// gas legacyOptimized: 136711
// gas legacy: 142861
// gas legacyOptimized: 137030
// f(uint256): 63 -> 0x20, 0x3f, 1780731860627700044960722568376592200742329637303199754547598369979440671, 14532552714582660066924456880521368950258152170031413196862950297402215316992
// gas irOptimized: 126467
// gas legacy: 159768
// gas legacyOptimized: 150641
// gas legacy: 160901
// gas legacyOptimized: 150960
// f(uint256): 12 -> 0x20, 0x0c, 0x0102030405060708090a0b0000000000000000000000000000000000000000
// gas legacy: 59345
// gas legacyOptimized: 57279
// f(uint256): 129 -> 0x20, 0x81, 1780731860627700044960722568376592200742329637303199754547598369979440671, 0x202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f, 29063324697304692433803953038474361308315562010425523193971352996434451193439, 0x606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f, -57896044618658097711785492504343953926634992332820282019728792003956564819968
// gas irOptimized: 353326
// gas legacy: 421067
// gas legacyOptimized: 402910
// gas legacy: 421700
// gas legacyOptimized: 402999

View File

@ -36,11 +36,11 @@ contract C {
// ----
// f() -> 0x40, 0x80, 6, 0x6162636465660000000000000000000000000000000000000000000000000000, 0x49, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738390000000000000000000000000000000000000000000000
// gas irOptimized: 179880
// gas legacy: 180676
// gas legacyOptimized: 180070
// gas legacy: 181099
// gas legacyOptimized: 180073
// g() -> 0x40, 0xc0, 0x49, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738390000000000000000000000000000000000000000000000, 0x11, 0x3132333435363738393233343536373839000000000000000000000000000000
// gas irOptimized: 107211
// gas legacy: 107877
// gas legacyOptimized: 107236
// gas legacy: 110253
// gas legacyOptimized: 107397
// h() -> 0x40, 0x60, 0x00, 0x00
// storageEmpty -> 1

View File

@ -47,5 +47,5 @@ contract C {
// ----
// f() -> 0xff
// gas irOptimized: 119584
// gas legacy: 128005
// gas legacyOptimized: 123446
// gas legacy: 132274
// gas legacyOptimized: 123756

View File

@ -8,8 +8,8 @@ contract c {
// ----
// set(): 1, 2, 3, 4, 5 -> true
// gas irOptimized: 177386
// gas legacy: 177653
// gas legacyOptimized: 177493
// gas legacy: 177970
// gas legacyOptimized: 177559
// storageEmpty -> 0
// reset() -> true
// storageEmpty -> 1

View File

@ -21,8 +21,8 @@ contract sender {
// ----
// (): 7 ->
// gas irOptimized: 110826
// gas legacy: 111071
// gas legacyOptimized: 111016
// gas legacy: 111408
// gas legacyOptimized: 111078
// val() -> 0
// forward(bool): true -> true
// val() -> 0x80

View File

@ -16,4 +16,4 @@ contract C {
// ====
// compileViaYul: false
// ----
// f() -> 0x6465616462656566313564656164000000000000000000000000000000000010
// f() -> 0x6465616462656566000000000000000000000000000000000000000000000010

View File

@ -19,5 +19,5 @@ contract C {
// ----
// f() -> 3
// gas irOptimized: 128172
// gas legacy: 130181
// gas legacyOptimized: 129198
// gas legacy: 130757
// gas legacyOptimized: 129144

View File

@ -12,5 +12,5 @@ contract C {
// ----
// f() -> 0x20, 0x02, 0x40, 0x80, 3, 0x6162630000000000000000000000000000000000000000000000000000000000, 0x99, 44048183304486788312148433451363384677562265908331949128489393215789685032262, 32241931068525137014058842823026578386641954854143559838526554899205067598957, 49951309422467613961193228765530489307475214998374779756599339590522149884499, 0x54555658595a6162636465666768696a6b6c6d6e6f707172737475767778797a, 0x4142434445464748494a4b4c4d4e4f5051525354555658595a00000000000000
// gas irOptimized: 202952
// gas legacy: 204441
// gas legacyOptimized: 203419
// gas legacy: 204912
// gas legacyOptimized: 203437

View File

@ -17,5 +17,5 @@ contract c {
// ----
// test1() -> true
// gas irOptimized: 207928
// gas legacy: 254650
// gas legacyOptimized: 247384
// gas legacy: 254905
// gas legacyOptimized: 247415

View File

@ -14,5 +14,5 @@ contract C {
// ----
// f() ->
// gas irOptimized: 179173
// gas legacy: 180602
// gas legacyOptimized: 180385
// gas legacy: 181066
// gas legacyOptimized: 180435

View File

@ -0,0 +1,37 @@
contract C {
event ev(uint[], uint);
bytes public s;
function h() external returns (bytes memory) {
uint[] memory x = new uint[](2);
emit ev(x, 0x21);
bytes memory m = new bytes(63);
s = m;
s.push();
return s;
}
function g() external returns (bytes memory) {
bytes memory m = new bytes(63);
assembly {
mstore8(add(m, add(32, 63)), 0x42)
}
s = m;
s.push();
return s;
}
function f(bytes calldata c) external returns (bytes memory) {
s = c;
s.push();
return s;
}
}
// ====
// compileViaYul: also
// ----
// constructor() ->
// gas irOptimized: 521983
// gas legacy: 731840
// gas legacyOptimized: 494859
// h() -> 0x20, 0x40, 0x00, 0
// ~ emit ev(uint256[],uint256): 0x40, 0x21, 0x02, 0x00, 0x00
// g() -> 0x20, 0x40, 0, 0x00
// f(bytes): 0x20, 33, 0, -1 -> 0x20, 0x22, 0, 0xff00000000000000000000000000000000000000000000000000000000000000

View File

@ -11,8 +11,8 @@ contract c {
// ----
// (): 1, 2, 3, 4, 5 ->
// gas irOptimized: 155158
// gas legacy: 155249
// gas legacyOptimized: 155212
// gas legacy: 155483
// gas legacyOptimized: 155303
// checkIfDataIsEmpty() -> false
// sendMessage() -> true, 0x40, 0
// checkIfDataIsEmpty() -> true

View File

@ -25,5 +25,5 @@ contract Creator {
// ----
// f(uint256,bytes): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> 7, "h"
// gas irOptimized: 282398
// gas legacy: 428711
// gas legacyOptimized: 297922
// gas legacy: 429047
// gas legacyOptimized: 297958

View File

@ -9,7 +9,7 @@ contract Test {
// ----
// constructor(): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" ->
// gas irOptimized: 273340
// gas legacy: 309607
// gas legacyOptimized: 260566
// gas legacy: 317746
// gas legacyOptimized: 262368
// m_x() -> 7
// m_s() -> 0x20, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz"

View File

@ -24,8 +24,8 @@ contract c {
// storageEmpty -> 1
// set(uint256,bytes,uint256): 12, 0x60, 13, 33, "12345678901234567890123456789012", "3" -> true
// gas irOptimized: 133599
// gas legacy: 134433
// gas legacyOptimized: 133876
// gas legacy: 134654
// gas legacyOptimized: 133882
// test(uint256): 32 -> "3"
// storageEmpty -> 0
// copy() -> true

View File

@ -17,8 +17,8 @@ contract C {
// ----
// constructor() ->
// gas irOptimized: 177507
// gas legacy: 240889
// gas legacyOptimized: 155314
// gas legacy: 249207
// gas legacyOptimized: 157489
// initCode() -> 0x20, 0
// f() -> true
// g() -> 0

View File

@ -35,5 +35,5 @@ contract C {
// ----
// f(bytes): 0x20, 0x5, "abcde" -> 0
// gas irOptimized: 239194
// gas legacy: 240349
// gas legacyOptimized: 239673
// gas legacy: 240541
// gas legacyOptimized: 239654

View File

@ -21,5 +21,5 @@ contract C {
// ----
// g() -> 2, 6
// gas irOptimized: 178677
// gas legacy: 180753
// gas legacyOptimized: 179472
// gas legacy: 180945
// gas legacyOptimized: 179460