mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #8924 from ethereum/arraySliceBug
Fix array slice bug.
This commit is contained in:
commit
e9446475bb
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
Important Bugfixes:
|
Important Bugfixes:
|
||||||
* Add missing callvalue check to the creation code of a contract that does not define a constructor but has a base that does define a constructor.
|
* Add missing callvalue check to the creation code of a contract that does not define a constructor but has a base that does define a constructor.
|
||||||
|
* Disallow index range accesses for arrays with dynamically encoded base types.
|
||||||
|
|
||||||
|
|
||||||
Language Features:
|
Language Features:
|
||||||
|
@ -1,4 +1,15 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"name": "ArraySliceDynamicallyEncodedBaseType",
|
||||||
|
"summary": "Accessing array slices of arrays with dynamically encoded base types (e.g. multi-dimensional arrays) can result in invalid data being read.",
|
||||||
|
"description": "For arrays with dynamically sized base types, index range accesses that use a start expression that is non-zero will result in invalid array slices. Any index access to such array slices will result in data being read from incorrect calldata offsets. Array slices are only supported for dynamic calldata types and all problematic type require ABIEncoderV2 to be enabled.",
|
||||||
|
"introduced": "0.6.0",
|
||||||
|
"fixed": "0.6.8",
|
||||||
|
"severity": "very low",
|
||||||
|
"conditions": {
|
||||||
|
"ABIEncoderV2": true
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "ImplicitConstructorCallvalueCheck",
|
"name": "ImplicitConstructorCallvalueCheck",
|
||||||
"summary": "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.",
|
"summary": "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.",
|
||||||
|
@ -1082,6 +1082,7 @@
|
|||||||
},
|
},
|
||||||
"0.6.0": {
|
"0.6.0": {
|
||||||
"bugs": [
|
"bugs": [
|
||||||
|
"ArraySliceDynamicallyEncodedBaseType",
|
||||||
"ImplicitConstructorCallvalueCheck",
|
"ImplicitConstructorCallvalueCheck",
|
||||||
"TupleAssignmentMultiStackSlotComponents",
|
"TupleAssignmentMultiStackSlotComponents",
|
||||||
"MemoryArrayCreationOverflow",
|
"MemoryArrayCreationOverflow",
|
||||||
@ -1091,6 +1092,7 @@
|
|||||||
},
|
},
|
||||||
"0.6.1": {
|
"0.6.1": {
|
||||||
"bugs": [
|
"bugs": [
|
||||||
|
"ArraySliceDynamicallyEncodedBaseType",
|
||||||
"ImplicitConstructorCallvalueCheck",
|
"ImplicitConstructorCallvalueCheck",
|
||||||
"TupleAssignmentMultiStackSlotComponents",
|
"TupleAssignmentMultiStackSlotComponents",
|
||||||
"MemoryArrayCreationOverflow"
|
"MemoryArrayCreationOverflow"
|
||||||
@ -1099,6 +1101,7 @@
|
|||||||
},
|
},
|
||||||
"0.6.2": {
|
"0.6.2": {
|
||||||
"bugs": [
|
"bugs": [
|
||||||
|
"ArraySliceDynamicallyEncodedBaseType",
|
||||||
"ImplicitConstructorCallvalueCheck",
|
"ImplicitConstructorCallvalueCheck",
|
||||||
"TupleAssignmentMultiStackSlotComponents",
|
"TupleAssignmentMultiStackSlotComponents",
|
||||||
"MemoryArrayCreationOverflow"
|
"MemoryArrayCreationOverflow"
|
||||||
@ -1107,6 +1110,7 @@
|
|||||||
},
|
},
|
||||||
"0.6.3": {
|
"0.6.3": {
|
||||||
"bugs": [
|
"bugs": [
|
||||||
|
"ArraySliceDynamicallyEncodedBaseType",
|
||||||
"ImplicitConstructorCallvalueCheck",
|
"ImplicitConstructorCallvalueCheck",
|
||||||
"TupleAssignmentMultiStackSlotComponents",
|
"TupleAssignmentMultiStackSlotComponents",
|
||||||
"MemoryArrayCreationOverflow"
|
"MemoryArrayCreationOverflow"
|
||||||
@ -1115,6 +1119,7 @@
|
|||||||
},
|
},
|
||||||
"0.6.4": {
|
"0.6.4": {
|
||||||
"bugs": [
|
"bugs": [
|
||||||
|
"ArraySliceDynamicallyEncodedBaseType",
|
||||||
"ImplicitConstructorCallvalueCheck",
|
"ImplicitConstructorCallvalueCheck",
|
||||||
"TupleAssignmentMultiStackSlotComponents",
|
"TupleAssignmentMultiStackSlotComponents",
|
||||||
"MemoryArrayCreationOverflow"
|
"MemoryArrayCreationOverflow"
|
||||||
@ -1123,6 +1128,7 @@
|
|||||||
},
|
},
|
||||||
"0.6.5": {
|
"0.6.5": {
|
||||||
"bugs": [
|
"bugs": [
|
||||||
|
"ArraySliceDynamicallyEncodedBaseType",
|
||||||
"ImplicitConstructorCallvalueCheck",
|
"ImplicitConstructorCallvalueCheck",
|
||||||
"TupleAssignmentMultiStackSlotComponents"
|
"TupleAssignmentMultiStackSlotComponents"
|
||||||
],
|
],
|
||||||
@ -1130,12 +1136,14 @@
|
|||||||
},
|
},
|
||||||
"0.6.6": {
|
"0.6.6": {
|
||||||
"bugs": [
|
"bugs": [
|
||||||
|
"ArraySliceDynamicallyEncodedBaseType",
|
||||||
"ImplicitConstructorCallvalueCheck"
|
"ImplicitConstructorCallvalueCheck"
|
||||||
],
|
],
|
||||||
"released": "2020-04-09"
|
"released": "2020-04-09"
|
||||||
},
|
},
|
||||||
"0.6.7": {
|
"0.6.7": {
|
||||||
"bugs": [
|
"bugs": [
|
||||||
|
"ArraySliceDynamicallyEncodedBaseType",
|
||||||
"ImplicitConstructorCallvalueCheck"
|
"ImplicitConstructorCallvalueCheck"
|
||||||
],
|
],
|
||||||
"released": "2020-05-04"
|
"released": "2020-05-04"
|
||||||
|
@ -2864,6 +2864,8 @@ bool TypeChecker::visit(IndexRangeAccess const& _access)
|
|||||||
|
|
||||||
if (arrayType->location() != DataLocation::CallData || !arrayType->isDynamicallySized())
|
if (arrayType->location() != DataLocation::CallData || !arrayType->isDynamicallySized())
|
||||||
m_errorReporter.typeError(1227_error, _access.location(), "Index range access is only supported for dynamic calldata arrays.");
|
m_errorReporter.typeError(1227_error, _access.location(), "Index range access is only supported for dynamic calldata arrays.");
|
||||||
|
else if (arrayType->baseType()->isDynamicallyEncoded())
|
||||||
|
m_errorReporter.typeError(1878_error, _access.location(), "Index range access is not supported for arrays with dynamically encoded base types.");
|
||||||
_access.annotation().type = TypeProvider::arraySlice(*arrayType);
|
_access.annotation().type = TypeProvider::arraySlice(*arrayType);
|
||||||
_access.annotation().isLValue = isLValue;
|
_access.annotation().isLValue = isLValue;
|
||||||
_access.annotation().isPure = isPure;
|
_access.annotation().isPure = isPure;
|
||||||
|
@ -990,7 +990,8 @@ void CompilerUtils::convertType(
|
|||||||
solAssert(_targetType == typeOnStack.arrayType(), "");
|
solAssert(_targetType == typeOnStack.arrayType(), "");
|
||||||
solUnimplementedAssert(
|
solUnimplementedAssert(
|
||||||
typeOnStack.arrayType().location() == DataLocation::CallData &&
|
typeOnStack.arrayType().location() == DataLocation::CallData &&
|
||||||
typeOnStack.arrayType().isDynamicallySized(),
|
typeOnStack.arrayType().isDynamicallySized() &&
|
||||||
|
!typeOnStack.arrayType().baseType()->isDynamicallyEncoded(),
|
||||||
""
|
""
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
@ -1769,7 +1769,12 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
|
|||||||
case Type::Category::ArraySlice:
|
case Type::Category::ArraySlice:
|
||||||
{
|
{
|
||||||
auto const& arrayType = dynamic_cast<ArraySliceType const&>(baseType).arrayType();
|
auto const& arrayType = dynamic_cast<ArraySliceType const&>(baseType).arrayType();
|
||||||
solAssert(arrayType.location() == DataLocation::CallData && arrayType.isDynamicallySized(), "");
|
solAssert(
|
||||||
|
arrayType.location() == DataLocation::CallData &&
|
||||||
|
arrayType.isDynamicallySized() &&
|
||||||
|
!arrayType.baseType()->isDynamicallyEncoded(),
|
||||||
|
""
|
||||||
|
);
|
||||||
solAssert(_indexAccess.indexExpression(), "Index expression expected.");
|
solAssert(_indexAccess.indexExpression(), "Index expression expected.");
|
||||||
|
|
||||||
acceptAndConvert(*_indexAccess.indexExpression(), *TypeProvider::uint256(), true);
|
acceptAndConvert(*_indexAccess.indexExpression(), *TypeProvider::uint256(), true);
|
||||||
@ -1852,7 +1857,12 @@ bool ExpressionCompiler::visit(IndexRangeAccess const& _indexAccess)
|
|||||||
arrayType = &sliceType->arrayType();
|
arrayType = &sliceType->arrayType();
|
||||||
|
|
||||||
solAssert(arrayType, "");
|
solAssert(arrayType, "");
|
||||||
solUnimplementedAssert(arrayType->location() == DataLocation::CallData && arrayType->isDynamicallySized(), "");
|
solUnimplementedAssert(
|
||||||
|
arrayType->location() == DataLocation::CallData &&
|
||||||
|
arrayType->isDynamicallySized() &&
|
||||||
|
!arrayType->baseType()->isDynamicallyEncoded(),
|
||||||
|
""
|
||||||
|
);
|
||||||
|
|
||||||
if (_indexAccess.startExpression())
|
if (_indexAccess.startExpression())
|
||||||
acceptAndConvert(*_indexAccess.startExpression(), *TypeProvider::uint256());
|
acceptAndConvert(*_indexAccess.startExpression(), *TypeProvider::uint256());
|
||||||
|
@ -1599,6 +1599,7 @@ string YulUtilFunctions::conversionFunction(Type const& _from, Type const& _to)
|
|||||||
ArraySliceType const& fromType = dynamic_cast<ArraySliceType const&>(_from);
|
ArraySliceType const& fromType = dynamic_cast<ArraySliceType const&>(_from);
|
||||||
ArrayType const& targetType = dynamic_cast<ArrayType const&>(_to);
|
ArrayType const& targetType = dynamic_cast<ArrayType const&>(_to);
|
||||||
|
|
||||||
|
solAssert(!fromType.arrayType().baseType()->isDynamicallyEncoded(), "");
|
||||||
solAssert(
|
solAssert(
|
||||||
*fromType.arrayType().baseType() == *targetType.baseType(),
|
*fromType.arrayType().baseType() == *targetType.baseType(),
|
||||||
"Converting arrays of different type is not possible"
|
"Converting arrays of different type is not possible"
|
||||||
|
@ -2,9 +2,8 @@ pragma experimental ABIEncoderV2;
|
|||||||
contract C {
|
contract C {
|
||||||
function f(uint256[][] calldata x) external pure {
|
function f(uint256[][] calldata x) external pure {
|
||||||
x[0][1:2];
|
x[0][1:2];
|
||||||
x[1:2][1:2];
|
uint256 a = x[0][1:2][1:2][1:][3:][0];
|
||||||
uint256 a = x[1:2][1:2][1:][3:][0][2];
|
uint256 b = x[1][1:][3:4][1:][2:3][0];
|
||||||
uint256 b = x[1:][3:4][1][1:][2:3][0];
|
|
||||||
a; b;
|
a; b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
contract C {
|
||||||
|
function f(uint256[][] calldata x) external pure {
|
||||||
|
x[1:2];
|
||||||
|
x[:];
|
||||||
|
x[1:];
|
||||||
|
x[:2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError: (110-116): Index range access is not supported for arrays with dynamically encoded base types.
|
||||||
|
// TypeError: (126-130): Index range access is not supported for arrays with dynamically encoded base types.
|
||||||
|
// TypeError: (140-145): Index range access is not supported for arrays with dynamically encoded base types.
|
||||||
|
// TypeError: (155-160): Index range access is not supported for arrays with dynamically encoded base types.
|
Loading…
Reference in New Issue
Block a user