From e298c8ea00255f0f602d3e98fcab5f4b96290bdf Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Fri, 21 Sep 2018 21:46:54 +0100 Subject: [PATCH] Do not crash on invalid indexed access --- libsolidity/analysis/TypeChecker.cpp | 34 ++++++++++++------- libsolidity/analysis/TypeChecker.h | 2 +- .../array_multidim_overflow_index.sol | 5 +++ .../indexing/array_multidim_rational.sol | 5 +++ .../indexing/fixedbytes_negative_index.sol | 2 +- .../indexing/fixedbytes_noninteger_index.sol | 3 ++ 6 files changed, 36 insertions(+), 15 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 3d119c8274c9..7facde666be5 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -2280,15 +2280,17 @@ bool TypeChecker::visit(IndexAccess const& _access) resultType = make_shared(make_shared(DataLocation::Memory, typeType.actualType())); else { - expectType(*index, IntegerType(256)); - if (auto length = dynamic_cast(type(*index).get())) - resultType = make_shared(make_shared( - DataLocation::Memory, - typeType.actualType(), - length->literalValue(nullptr) - )); - else + if (!expectType(*index, IntegerType(256))) m_errorReporter.fatalTypeError(index->location(), "Integer constant expected."); + + auto length = dynamic_cast(type(*index).get()); + solAssert(length, ""); + + resultType = make_shared(make_shared( + DataLocation::Memory, + typeType.actualType(), + length->literalValue(nullptr) + )); } break; } @@ -2299,10 +2301,14 @@ bool TypeChecker::visit(IndexAccess const& _access) m_errorReporter.typeError(_access.location(), "Index expression cannot be omitted."); else { - expectType(*index, IntegerType(256)); - if (auto integerType = dynamic_cast(type(*index).get())) - if (bytesType.numBytes() <= integerType->literalValue(nullptr)) - m_errorReporter.typeError(_access.location(), "Out of bounds array access."); + if (!expectType(*index, IntegerType(256))) + m_errorReporter.fatalTypeError(_access.location(), "Integer constant expected."); + + auto integerType = dynamic_cast(type(*index).get()); + solAssert(integerType, ""); + + if (bytesType.numBytes() <= integerType->literalValue(nullptr)) + m_errorReporter.typeError(_access.location(), "Out of bounds array access."); } resultType = make_shared(1); isLValue = false; // @todo this heavily depends on how it is embedded @@ -2470,7 +2476,7 @@ Declaration const& TypeChecker::dereference(UserDefinedTypeName const& _typeName return *_typeName.annotation().referencedDeclaration; } -void TypeChecker::expectType(Expression const& _expression, Type const& _expectedType) +bool TypeChecker::expectType(Expression const& _expression, Type const& _expectedType) { _expression.accept(*this); if (!type(_expression)->isImplicitlyConvertibleTo(_expectedType)) @@ -2499,7 +2505,9 @@ void TypeChecker::expectType(Expression const& _expression, Type const& _expecte _expectedType.toString() + "." ); + return false; } + return true; } void TypeChecker::requireLValue(Expression const& _expression) diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h index 8d25a88ea96b..6ea99ca20bfc 100644 --- a/libsolidity/analysis/TypeChecker.h +++ b/libsolidity/analysis/TypeChecker.h @@ -143,7 +143,7 @@ class TypeChecker: private ASTConstVisitor /// Runs type checks on @a _expression to infer its type and then checks that it is implicitly /// convertible to @a _expectedType. - void expectType(Expression const& _expression, Type const& _expectedType); + bool expectType(Expression const& _expression, Type const& _expectedType); /// Runs type checks on @a _expression to infer its type and then checks that it is an LValue. void requireLValue(Expression const& _expression); diff --git a/test/libsolidity/syntaxTests/indexing/array_multidim_overflow_index.sol b/test/libsolidity/syntaxTests/indexing/array_multidim_overflow_index.sol index 7ce7fb24f01c..a9a3dc327a1c 100644 --- a/test/libsolidity/syntaxTests/indexing/array_multidim_overflow_index.sol +++ b/test/libsolidity/syntaxTests/indexing/array_multidim_overflow_index.sol @@ -4,3 +4,8 @@ contract C { a[8**90][8**90][1 - 8**90]; } } +// ---- +// TypeError: (67-72): Type int_const 1897...(74 digits omitted)...1424 is not implicitly convertible to expected type uint256. +// TypeError: (74-79): Type int_const 1897...(74 digits omitted)...1424 is not implicitly convertible to expected type uint256. +// TypeError: (81-90): Type int_const -189...(75 digits omitted)...1423 is not implicitly convertible to expected type uint256. +// TypeError: (65-91): Integer constant expected. diff --git a/test/libsolidity/syntaxTests/indexing/array_multidim_rational.sol b/test/libsolidity/syntaxTests/indexing/array_multidim_rational.sol index 24310c290c02..850f6db9a33a 100644 --- a/test/libsolidity/syntaxTests/indexing/array_multidim_rational.sol +++ b/test/libsolidity/syntaxTests/indexing/array_multidim_rational.sol @@ -4,3 +4,8 @@ contract C { a[8**90][8**90][8**90*0.1]; } } +// ---- +// TypeError: (67-72): Type int_const 1897...(74 digits omitted)...1424 is not implicitly convertible to expected type uint256. +// TypeError: (74-79): Type int_const 1897...(74 digits omitted)...1424 is not implicitly convertible to expected type uint256. +// TypeError: (81-90): Type rational_const 9485...(73 digits omitted)...5712 / 5 is not implicitly convertible to expected type uint256. +// TypeError: (65-91): Integer constant expected. diff --git a/test/libsolidity/syntaxTests/indexing/fixedbytes_negative_index.sol b/test/libsolidity/syntaxTests/indexing/fixedbytes_negative_index.sol index 914feaed9a83..56f05d3a09fa 100644 --- a/test/libsolidity/syntaxTests/indexing/fixedbytes_negative_index.sol +++ b/test/libsolidity/syntaxTests/indexing/fixedbytes_negative_index.sol @@ -6,4 +6,4 @@ contract C { } // ---- // TypeError: (58-60): Type int_const -1 is not implicitly convertible to expected type uint256. -// TypeError: (56-61): Out of bounds array access. +// TypeError: (56-61): Integer constant expected. diff --git a/test/libsolidity/syntaxTests/indexing/fixedbytes_noninteger_index.sol b/test/libsolidity/syntaxTests/indexing/fixedbytes_noninteger_index.sol index 0821c39db770..4e3201965c6e 100644 --- a/test/libsolidity/syntaxTests/indexing/fixedbytes_noninteger_index.sol +++ b/test/libsolidity/syntaxTests/indexing/fixedbytes_noninteger_index.sol @@ -4,3 +4,6 @@ contract C { b[888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888]; } } +// ---- +// TypeError: (58-169): Type int_const 8888...(103 digits omitted)...8888 is not implicitly convertible to expected type uint256. +// TypeError: (56-170): Integer constant expected.