diff options
author | chriseth <chris@ethereum.org> | 2016-11-25 23:22:12 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-11-25 23:22:12 +0800 |
commit | 3a8a0708ff6cb502603fe2d8d1afa6c3e3b2a6ab (patch) | |
tree | 18ceb911719f0e7f48efa614ba550e8adbc68571 /libsolidity/codegen/CompilerUtils.cpp | |
parent | 721b6a969685e99078e296d88135ef84f6c001eb (diff) | |
parent | 0be58595036d3411124bc8b39f9d151790d950b4 (diff) | |
download | dexon-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.cpp | 21 |
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) |