aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/codegen/CompilerUtils.cpp
diff options
context:
space:
mode:
authorchriseth <chris@ethereum.org>2016-11-25 23:22:12 +0800
committerGitHub <noreply@github.com>2016-11-25 23:22:12 +0800
commit3a8a0708ff6cb502603fe2d8d1afa6c3e3b2a6ab (patch)
tree18ceb911719f0e7f48efa614ba550e8adbc68571 /libsolidity/codegen/CompilerUtils.cpp
parent721b6a969685e99078e296d88135ef84f6c001eb (diff)
parent0be58595036d3411124bc8b39f9d151790d950b4 (diff)
downloaddexon-solidity-3a8a0708ff6cb502603fe2d8d1afa6c3e3b2a6ab.tar
dexon-solidity-3a8a0708ff6cb502603fe2d8d1afa6c3e3b2a6ab.tar.gz
dexon-solidity-3a8a0708ff6cb502603fe2d8d1afa6c3e3b2a6ab.tar.bz2
dexon-solidity-3a8a0708ff6cb502603fe2d8d1afa6c3e3b2a6ab.tar.lz
dexon-solidity-3a8a0708ff6cb502603fe2d8d1afa6c3e3b2a6ab.tar.xz
dexon-solidity-3a8a0708ff6cb502603fe2d8d1afa6c3e3b2a6ab.tar.zst
dexon-solidity-3a8a0708ff6cb502603fe2d8d1afa6c3e3b2a6ab.zip
Merge pull request #1381 from ethereum/overflown_enum_compared
Enum overflow checking before writing to storage
Diffstat (limited to 'libsolidity/codegen/CompilerUtils.cpp')
-rw-r--r--libsolidity/codegen/CompilerUtils.cpp21
1 files changed, 20 insertions, 1 deletions
diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp
index fe2b9c7e..d5361ac6 100644
--- a/libsolidity/codegen/CompilerUtils.cpp
+++ b/libsolidity/codegen/CompilerUtils.cpp
@@ -358,7 +358,7 @@ void CompilerUtils::pushCombinedFunctionEntryLabel(Declaration const& _function)
Instruction::OR;
}
-void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetType, bool _cleanupNeeded)
+void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetType, bool _cleanupNeeded, bool _chopSignBits)
{
// For a type extension, we need to remove all higher-order bits that we might have ignored in
// previous operations.
@@ -370,6 +370,12 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp
Type::Category targetTypeCategory = _targetType.category();
bool enumOverflowCheckPending = (targetTypeCategory == Type::Category::Enum || stackTypeCategory == Type::Category::Enum);
+ bool chopSignBitsPending = _chopSignBits && targetTypeCategory == Type::Category::Integer;
+ if (chopSignBitsPending)
+ {
+ const IntegerType& targetIntegerType = dynamic_cast<const IntegerType &>(_targetType);
+ chopSignBitsPending = targetIntegerType.isSigned();
+ }
switch (stackTypeCategory)
{
@@ -482,6 +488,14 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp
cleanHigherOrderBits(typeOnStack);
else if (_cleanupNeeded)
cleanHigherOrderBits(targetType);
+ if (chopSignBitsPending)
+ {
+ if (typeOnStack.numBits() < 256)
+ m_context
+ << ((u256(1) << typeOnStack.numBits()) - 1)
+ << Instruction::AND;
+ chopSignBitsPending = false;
+ }
}
}
break;
@@ -724,10 +738,15 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp
default:
// All other types should not be convertible to non-equal types.
solAssert(_typeOnStack == _targetType, "Invalid type conversion requested.");
+ if (_cleanupNeeded && _targetType.canBeStored() && _targetType.storageBytes() < 32)
+ m_context
+ << ((u256(1) << (8 * _targetType.storageBytes())) - 1)
+ << Instruction::AND;
break;
}
solAssert(!enumOverflowCheckPending, "enum overflow checking missing.");
+ solAssert(!chopSignBitsPending, "forgot to chop the sign bits.");
}
void CompilerUtils::pushZeroValue(Type const& _type)