mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #1266 from ethereum/fixcrash
Fix a crash related to invalid number literals.
This commit is contained in:
commit
067109e1ae
@ -12,7 +12,8 @@ Bugfixes:
|
|||||||
* Commandline interface: Disallow unknown options in ``solc``.
|
* Commandline interface: Disallow unknown options in ``solc``.
|
||||||
* Name resolver: Allow inheritance of ``enum`` definitions.
|
* Name resolver: Allow inheritance of ``enum`` definitions.
|
||||||
* Type checker: Proper type checking for bound functions.
|
* Type checker: Proper type checking for bound functions.
|
||||||
* Type checker: fix crash related to invalid fixed point constants
|
* Type checker: fixed crash related to invalid fixed point constants
|
||||||
|
* Type checker: fixed crash related to invalid literal numbers.
|
||||||
* Code generator: expect zero stack increase after ``super`` as an expression.
|
* Code generator: expect zero stack increase after ``super`` as an expression.
|
||||||
* Code Generator: fixed an internal compiler error for ``L.Foo`` for ``enum Foo`` defined in library ``L``.
|
* Code Generator: fixed an internal compiler error for ``L.Foo`` for ``enum Foo`` defined in library ``L``.
|
||||||
* Inline assembly: support the ``address`` opcode.
|
* Inline assembly: support the ``address`` opcode.
|
||||||
|
@ -880,6 +880,10 @@ bool TypeChecker::visit(Conditional const& _conditional)
|
|||||||
|
|
||||||
TypePointer trueType = type(_conditional.trueExpression())->mobileType();
|
TypePointer trueType = type(_conditional.trueExpression())->mobileType();
|
||||||
TypePointer falseType = type(_conditional.falseExpression())->mobileType();
|
TypePointer falseType = type(_conditional.falseExpression())->mobileType();
|
||||||
|
if (!trueType)
|
||||||
|
fatalTypeError(_conditional.trueExpression().location(), "Invalid mobile type.");
|
||||||
|
if (!falseType)
|
||||||
|
fatalTypeError(_conditional.falseExpression().location(), "Invalid mobile type.");
|
||||||
|
|
||||||
TypePointer commonType = Type::commonType(trueType, falseType);
|
TypePointer commonType = Type::commonType(trueType, falseType);
|
||||||
if (!commonType)
|
if (!commonType)
|
||||||
@ -986,10 +990,16 @@ bool TypeChecker::visit(TupleExpression const& _tuple)
|
|||||||
types.push_back(type(*components[i]));
|
types.push_back(type(*components[i]));
|
||||||
if (_tuple.isInlineArray())
|
if (_tuple.isInlineArray())
|
||||||
solAssert(!!types[i], "Inline array cannot have empty components");
|
solAssert(!!types[i], "Inline array cannot have empty components");
|
||||||
if (i == 0 && _tuple.isInlineArray())
|
if (_tuple.isInlineArray())
|
||||||
inlineArrayType = types[i]->mobileType();
|
{
|
||||||
else if (_tuple.isInlineArray() && inlineArrayType)
|
if ((i == 0 || inlineArrayType) && !types[i]->mobileType())
|
||||||
inlineArrayType = Type::commonType(inlineArrayType, types[i]->mobileType());
|
fatalTypeError(components[i]->location(), "Invalid mobile type.");
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
inlineArrayType = types[i]->mobileType();
|
||||||
|
else if (inlineArrayType)
|
||||||
|
inlineArrayType = Type::commonType(inlineArrayType, types[i]->mobileType());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
types.push_back(TypePointer());
|
types.push_back(TypePointer());
|
||||||
|
@ -198,7 +198,9 @@ TypePointer Type::forLiteral(Literal const& _literal)
|
|||||||
|
|
||||||
TypePointer Type::commonType(TypePointer const& _a, TypePointer const& _b)
|
TypePointer Type::commonType(TypePointer const& _a, TypePointer const& _b)
|
||||||
{
|
{
|
||||||
if (_b->isImplicitlyConvertibleTo(*_a))
|
if (!_a || !_b)
|
||||||
|
return TypePointer();
|
||||||
|
else if (_b->isImplicitlyConvertibleTo(*_a))
|
||||||
return _a;
|
return _a;
|
||||||
else if (_a->isImplicitlyConvertibleTo(*_b))
|
else if (_a->isImplicitlyConvertibleTo(*_b))
|
||||||
return _b;
|
return _b;
|
||||||
@ -1661,7 +1663,17 @@ TypePointer TupleType::mobileType() const
|
|||||||
{
|
{
|
||||||
TypePointers mobiles;
|
TypePointers mobiles;
|
||||||
for (auto const& c: components())
|
for (auto const& c: components())
|
||||||
mobiles.push_back(c ? c->mobileType() : TypePointer());
|
{
|
||||||
|
if (c)
|
||||||
|
{
|
||||||
|
auto mt = c->mobileType();
|
||||||
|
if (!mt)
|
||||||
|
return TypePointer();
|
||||||
|
mobiles.push_back(mt);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mobiles.push_back(TypePointer());
|
||||||
|
}
|
||||||
return make_shared<TupleType>(mobiles);
|
return make_shared<TupleType>(mobiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,8 +368,11 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp
|
|||||||
m_context << (u256(1) << (256 - targetBytesType.numBytes() * 8)) << Instruction::MUL;
|
m_context << (u256(1) << (256 - targetBytesType.numBytes() * 8)) << Instruction::MUL;
|
||||||
}
|
}
|
||||||
else if (targetTypeCategory == Type::Category::Enum)
|
else if (targetTypeCategory == Type::Category::Enum)
|
||||||
|
{
|
||||||
|
solAssert(_typeOnStack.mobileType(), "");
|
||||||
// just clean
|
// just clean
|
||||||
convertType(_typeOnStack, *_typeOnStack.mobileType(), true);
|
convertType(_typeOnStack, *_typeOnStack.mobileType(), true);
|
||||||
|
}
|
||||||
else if (targetTypeCategory == Type::Category::FixedPoint)
|
else if (targetTypeCategory == Type::Category::FixedPoint)
|
||||||
{
|
{
|
||||||
solAssert(
|
solAssert(
|
||||||
|
@ -56,8 +56,10 @@ void ExpressionCompiler::appendStateVariableInitialization(VariableDeclaration c
|
|||||||
if (_varDecl.annotation().type->dataStoredIn(DataLocation::Storage))
|
if (_varDecl.annotation().type->dataStoredIn(DataLocation::Storage))
|
||||||
{
|
{
|
||||||
// reference type, only convert value to mobile type and do final conversion in storeValue.
|
// reference type, only convert value to mobile type and do final conversion in storeValue.
|
||||||
utils().convertType(*type, *type->mobileType());
|
auto mt = type->mobileType();
|
||||||
type = type->mobileType();
|
solAssert(mt, "");
|
||||||
|
utils().convertType(*type, *mt);
|
||||||
|
type = mt;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1437,11 +1439,17 @@ void ExpressionCompiler::appendExternalFunctionCall(
|
|||||||
// Evaluate arguments.
|
// Evaluate arguments.
|
||||||
TypePointers argumentTypes;
|
TypePointers argumentTypes;
|
||||||
TypePointers parameterTypes = _functionType.parameterTypes();
|
TypePointers parameterTypes = _functionType.parameterTypes();
|
||||||
bool manualFunctionId =
|
bool manualFunctionId = false;
|
||||||
|
if (
|
||||||
(funKind == FunctionKind::Bare || funKind == FunctionKind::BareCallCode || funKind == FunctionKind::BareDelegateCall) &&
|
(funKind == FunctionKind::Bare || funKind == FunctionKind::BareCallCode || funKind == FunctionKind::BareDelegateCall) &&
|
||||||
!_arguments.empty() &&
|
!_arguments.empty()
|
||||||
_arguments.front()->annotation().type->mobileType()->calldataEncodedSize(false) ==
|
)
|
||||||
|
{
|
||||||
|
solAssert(_arguments.front()->annotation().type->mobileType(), "");
|
||||||
|
manualFunctionId =
|
||||||
|
_arguments.front()->annotation().type->mobileType()->calldataEncodedSize(false) ==
|
||||||
CompilerUtils::dataStartOffset;
|
CompilerUtils::dataStartOffset;
|
||||||
|
}
|
||||||
if (manualFunctionId)
|
if (manualFunctionId)
|
||||||
{
|
{
|
||||||
// If we have a Bare* and the first type has exactly 4 bytes, use it as
|
// If we have a Bare* and the first type has exactly 4 bytes, use it as
|
||||||
|
@ -4175,7 +4175,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_in_modifier)
|
|||||||
modifier m {
|
modifier m {
|
||||||
uint a = 1;
|
uint a = 1;
|
||||||
assembly {
|
assembly {
|
||||||
a := 2
|
a := 2
|
||||||
}
|
}
|
||||||
_;
|
_;
|
||||||
}
|
}
|
||||||
@ -4193,7 +4193,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_storage)
|
|||||||
uint x = 1;
|
uint x = 1;
|
||||||
function f() {
|
function f() {
|
||||||
assembly {
|
assembly {
|
||||||
x := 2
|
x := 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4208,7 +4208,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_storage_in_modifiers)
|
|||||||
uint x = 1;
|
uint x = 1;
|
||||||
modifier m {
|
modifier m {
|
||||||
assembly {
|
assembly {
|
||||||
x := 2
|
x := 2
|
||||||
}
|
}
|
||||||
_;
|
_;
|
||||||
}
|
}
|
||||||
@ -4219,6 +4219,19 @@ BOOST_AUTO_TEST_CASE(inline_assembly_storage_in_modifiers)
|
|||||||
BOOST_CHECK(expectError(text, false) == Error::Type::DeclarationError);
|
BOOST_CHECK(expectError(text, false) == Error::Type::DeclarationError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(invalid_mobile_type)
|
||||||
|
{
|
||||||
|
char const* text = R"(
|
||||||
|
contract C {
|
||||||
|
function f() {
|
||||||
|
// Invalid number
|
||||||
|
[1, 78901234567890123456789012345678901234567890123456789345678901234567890012345678012345678901234567];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
BOOST_CHECK(expectError(text, false) == Error::Type::TypeError);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user