Improve support for unit and global

- Remove Balance IR (BREAKING CHANGE), and use solidity function instead
- Add support for addr.code / addr/codehash
- Add block.basefee support
- Improve bytes.concat support
- Add type early on for convert operator (useful for
.balance/.code/.codehash detection)

Replacing Balance by a solidity function allows to ease the analysis,
and prevent adding an IR opcode per address.function (code/codehash)

Additionally this PR add thorough tests based on
https://docs.soliditylang.org/en/latest/units-and-global-variables.html
for all the different solidity versions.
pull/985/head
Josselin 3 years ago
parent 5de54f7089
commit b85d9e8cbf
  1. 3
      slither/analyses/write/are_variables_written.py
  2. 5
      slither/core/cfg/node.py
  3. 6
      slither/core/declarations/solidity_variables.py
  4. 7
      slither/detectors/statements/incorrect_strict_equality.py
  5. 5
      slither/printers/guidance/echidna.py
  6. 49
      slither/slithir/convert.py
  7. 1
      slither/slithir/operations/__init__.py
  8. 24
      slither/slithir/operations/balance.py
  9. 5
      slither/slithir/operations/member.py
  10. 5
      slither/slithir/utils/ssa.py
  11. 3
      slither/tools/similarity/encode.py
  12. 29
      slither/visitors/slithir/expression_to_slithir.py
  13. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.0-legacy.zip
  14. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.1-legacy.zip
  15. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.10-legacy.zip
  16. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.11-legacy.zip
  17. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.12-compact.zip
  18. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.12-legacy.zip
  19. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.13-compact.zip
  20. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.13-legacy.zip
  21. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.14-compact.zip
  22. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.14-legacy.zip
  23. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.15-compact.zip
  24. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.15-legacy.zip
  25. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.16-compact.zip
  26. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.16-legacy.zip
  27. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.17-compact.zip
  28. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.17-legacy.zip
  29. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.18-compact.zip
  30. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.18-legacy.zip
  31. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.19-compact.zip
  32. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.19-legacy.zip
  33. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.2-legacy.zip
  34. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.20-compact.zip
  35. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.20-legacy.zip
  36. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.21-compact.zip
  37. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.21-legacy.zip
  38. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.22-compact.zip
  39. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.22-legacy.zip
  40. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.23-compact.zip
  41. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.23-legacy.zip
  42. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.24-compact.zip
  43. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.24-legacy.zip
  44. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.25-compact.zip
  45. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.25-legacy.zip
  46. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.26-compact.zip
  47. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.26-legacy.zip
  48. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.3-legacy.zip
  49. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.4-legacy.zip
  50. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.5-legacy.zip
  51. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.6-legacy.zip
  52. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.7-legacy.zip
  53. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.8-legacy.zip
  54. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.4.9-legacy.zip
  55. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.0-compact.zip
  56. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.0-legacy.zip
  57. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.1-compact.zip
  58. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.1-legacy.zip
  59. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.10-compact.zip
  60. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.10-legacy.zip
  61. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.11-compact.zip
  62. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.11-legacy.zip
  63. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.12-compact.zip
  64. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.12-legacy.zip
  65. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.13-compact.zip
  66. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.13-legacy.zip
  67. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.14-compact.zip
  68. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.14-legacy.zip
  69. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.15-compact.zip
  70. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.15-legacy.zip
  71. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.16-compact.zip
  72. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.16-legacy.zip
  73. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.17-compact.zip
  74. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.17-legacy.zip
  75. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.2-compact.zip
  76. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.2-legacy.zip
  77. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.3-compact.zip
  78. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.3-legacy.zip
  79. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.4-compact.zip
  80. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.4-legacy.zip
  81. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.5-compact.zip
  82. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.5-legacy.zip
  83. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.6-compact.zip
  84. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.6-legacy.zip
  85. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.7-compact.zip
  86. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.7-legacy.zip
  87. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.8-compact.zip
  88. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.8-legacy.zip
  89. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.9-compact.zip
  90. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.5.9-legacy.zip
  91. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.6.0-compact.zip
  92. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.6.0-legacy.zip
  93. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.6.1-compact.zip
  94. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.6.1-legacy.zip
  95. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.6.10-compact.zip
  96. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.6.10-legacy.zip
  97. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.6.11-compact.zip
  98. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.6.11-legacy.zip
  99. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.6.12-compact.zip
  100. BIN
      tests/ast-parsing/compile/units_and_global_variables-0.6.12-legacy.zip
  101. Some files were not shown because too many files have changed in this diff Show More

@ -13,7 +13,6 @@ from slither.slithir.operations import (
OperationWithLValue, OperationWithLValue,
SolidityCall, SolidityCall,
Length, Length,
Balance,
) )
from slither.slithir.variables import ReferenceVariable, TemporaryVariable from slither.slithir.variables import ReferenceVariable, TemporaryVariable
@ -65,7 +64,7 @@ def _visit(
continue continue
if isinstance(ir, (Index, Member)): if isinstance(ir, (Index, Member)):
refs[ir.lvalue] = ir.variable_left refs[ir.lvalue] = ir.variable_left
if isinstance(ir, (Length, Balance)): if isinstance(ir, Length):
refs[ir.lvalue] = ir.value refs[ir.lvalue] = ir.value
if ir.lvalue and not isinstance(ir.lvalue, (TemporaryVariable, ReferenceVariable)): if ir.lvalue and not isinstance(ir.lvalue, (TemporaryVariable, ReferenceVariable)):

@ -16,7 +16,6 @@ from slither.core.variables.variable import Variable
from slither.core.solidity_types import ElementaryType from slither.core.solidity_types import ElementaryType
from slither.slithir.convert import convert_expression from slither.slithir.convert import convert_expression
from slither.slithir.operations import ( from slither.slithir.operations import (
Balance,
HighLevelCall, HighLevelCall,
Index, Index,
InternalCall, InternalCall,
@ -875,7 +874,7 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
self._vars_read.append(origin) self._vars_read.append(origin)
if isinstance(ir, OperationWithLValue): if isinstance(ir, OperationWithLValue):
if isinstance(ir, (Index, Member, Length, Balance)): if isinstance(ir, (Index, Member, Length)):
continue # Don't consider Member and Index operations -> ReferenceVariable continue # Don't consider Member and Index operations -> ReferenceVariable
var = ir.lvalue var = ir.lvalue
if isinstance(var, ReferenceVariable): if isinstance(var, ReferenceVariable):
@ -959,7 +958,7 @@ class Node(SourceMapping, ChildFunction): # pylint: disable=too-many-public-met
self._ssa_vars_read.append(origin) self._ssa_vars_read.append(origin)
if isinstance(ir, OperationWithLValue): if isinstance(ir, OperationWithLValue):
if isinstance(ir, (Index, Member, Length, Balance)): if isinstance(ir, (Index, Member, Length)):
continue # Don't consider Member and Index operations -> ReferenceVariable continue # Don't consider Member and Index operations -> ReferenceVariable
var = ir.lvalue var = ir.lvalue
if isinstance(var, ReferenceVariable): if isinstance(var, ReferenceVariable):

@ -20,6 +20,7 @@ SOLIDITY_VARIABLES = {
} }
SOLIDITY_VARIABLES_COMPOSED = { SOLIDITY_VARIABLES_COMPOSED = {
"block.basefee": "uint",
"block.coinbase": "address", "block.coinbase": "address",
"block.difficulty": "uint256", "block.difficulty": "uint256",
"block.gaslimit": "uint256", "block.gaslimit": "uint256",
@ -69,10 +70,15 @@ SOLIDITY_FUNCTIONS: Dict[str, List[str]] = {
"abi.encodePacked()": ["bytes"], "abi.encodePacked()": ["bytes"],
"abi.encodeWithSelector()": ["bytes"], "abi.encodeWithSelector()": ["bytes"],
"abi.encodeWithSignature()": ["bytes"], "abi.encodeWithSignature()": ["bytes"],
"bytes.concat()": ["bytes"],
# abi.decode returns an a list arbitrary types # abi.decode returns an a list arbitrary types
"abi.decode()": [], "abi.decode()": [],
"type(address)": [], "type(address)": [],
"type()": [], # 0.6.8 changed type(address) to type() "type()": [], # 0.6.8 changed type(address) to type()
# The following are conversion from address.something
"balance(address)": ["uint256"],
"code(address)": ["bytes"],
"codehash(address)": ["bytes32"],
} }

@ -9,10 +9,10 @@ from slither.core.declarations.function_top_level import FunctionTopLevel
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.operations import ( from slither.slithir.operations import (
Assignment, Assignment,
Balance,
Binary, Binary,
BinaryType, BinaryType,
HighLevelCall, HighLevelCall,
SolidityCall,
) )
from slither.core.solidity_types import MappingType, ElementaryType from slither.core.solidity_types import MappingType, ElementaryType
@ -21,6 +21,7 @@ from slither.core.variables.state_variable import StateVariable
from slither.core.declarations.solidity_variables import ( from slither.core.declarations.solidity_variables import (
SolidityVariable, SolidityVariable,
SolidityVariableComposed, SolidityVariableComposed,
SolidityFunction,
) )
@ -78,7 +79,9 @@ contract Crowdsale{
for func in functions: for func in functions:
for node in func.nodes: for node in func.nodes:
for ir in node.irs_ssa: for ir in node.irs_ssa:
if isinstance(ir, Balance): if isinstance(ir, SolidityCall) and ir.function == SolidityFunction(
"balance(address)"
):
taints.append(ir.lvalue) taints.append(ir.lvalue)
if isinstance(ir, HighLevelCall): if isinstance(ir, HighLevelCall):
# print(ir.function.full_name) # print(ir.function.full_name)

@ -27,7 +27,6 @@ from slither.slithir.operations import (
InternalDynamicCall, InternalDynamicCall,
InternalCall, InternalCall,
TypeConversion, TypeConversion,
Balance,
) )
from slither.slithir.operations.binary import Binary from slither.slithir.operations.binary import Binary
from slither.slithir.variables import Constant from slither.slithir.variables import Constant
@ -288,7 +287,9 @@ def _use_balance(slither: SlitherCore) -> Dict[str, List[str]]:
for contract in slither.contracts: for contract in slither.contracts:
for function in contract.functions_entry_points: for function in contract.functions_entry_points:
for ir in function.all_slithir_operations(): for ir in function.all_slithir_operations():
if isinstance(ir, Balance): if isinstance(ir, SolidityCall) and ir.function == SolidityFunction(
"balance(address)"
):
ret[contract.name].append(_get_name(function)) ret[contract.name].append(_get_name(function))
if contract.name in ret: if contract.name in ret:
ret[contract.name] = list(set(ret[contract.name])) ret[contract.name] = list(set(ret[contract.name]))

@ -39,7 +39,6 @@ from slither.core.variables.variable import Variable
from slither.slithir.exceptions import SlithIRError from slither.slithir.exceptions import SlithIRError
from slither.slithir.operations import ( from slither.slithir.operations import (
Assignment, Assignment,
Balance,
Binary, Binary,
BinaryType, BinaryType,
Call, Call,
@ -605,15 +604,32 @@ def propagate_types(ir, node: "Node"): # pylint: disable=too-many-locals
length.lvalue.points_to = ir.variable_left length.lvalue.points_to = ir.variable_left
length.set_node(ir.node) length.set_node(ir.node)
return length return length
# This only happen for .balance/code/codehash access on a variable for which we dont know at
# early parsing time the type
# Like
# function return_addr() internal returns(addresss)
#
# return_addr().balance
# Here slithIR will incorrectly create a REF variable instead of a Temp variable
# However this pattern does not appear so often
if ( if (
ir.variable_right == "balance" ir.variable_right.name in ["balance", "code", "codehash"]
and not isinstance(ir.variable_left, Contract) and not isinstance(ir.variable_left, Contract)
and isinstance(ir.variable_left.type, ElementaryType) and isinstance(ir.variable_left.type, ElementaryType)
): ):
b = Balance(ir.variable_left, ir.lvalue) name = ir.variable_right.name + "(address)"
b.set_expression(ir.expression) sol_func = SolidityFunction(name)
b.set_node(ir.node) s = SolidityCall(
return b sol_func,
1,
ir.lvalue,
sol_func.return_type,
)
s.arguments.append(ir.variable_left)
s.set_expression(ir.expression)
s.lvalue.set_type(sol_func.return_type)
s.set_node(ir.node)
return s
if ( if (
ir.variable_right == "codesize" ir.variable_right == "codesize"
and not isinstance(ir.variable_left, Contract) and not isinstance(ir.variable_left, Contract)
@ -916,6 +932,18 @@ def extract_tmp_call(ins: TmpCall, contract: Optional[Contract]): # pylint: dis
internalcall.function_candidates = top_level_function_targets internalcall.function_candidates = top_level_function_targets
return internalcall return internalcall
if ins.ori.variable_left == ElementaryType("bytes") and ins.ori.variable_right == Constant(
"concat"
):
s = SolidityCall(
SolidityFunction("bytes.concat()"),
ins.nbr_arguments,
ins.lvalue,
ins.type_call,
)
s.set_expression(ins.expression)
return s
msgcall = HighLevelCall( msgcall = HighLevelCall(
ins.ori.variable_left, ins.ori.variable_left,
ins.ori.variable_right, ins.ori.variable_right,
@ -940,15 +968,6 @@ def extract_tmp_call(ins: TmpCall, contract: Optional[Contract]): # pylint: dis
if isinstance(ins.called, SolidityVariableComposed): if isinstance(ins.called, SolidityVariableComposed):
if str(ins.called) == "block.blockhash": if str(ins.called) == "block.blockhash":
ins.called = SolidityFunction("blockhash(uint256)") ins.called = SolidityFunction("blockhash(uint256)")
elif str(ins.called) == "this.balance":
s = SolidityCall(
SolidityFunction("this.balance()"),
ins.nbr_arguments,
ins.lvalue,
ins.type_call,
)
s.set_expression(ins.expression)
return s
if isinstance(ins.called, SolidityFunction): if isinstance(ins.called, SolidityFunction):
s = SolidityCall(ins.called, ins.nbr_arguments, ins.lvalue, ins.type_call) s = SolidityCall(ins.called, ins.nbr_arguments, ins.lvalue, ins.type_call)

@ -27,7 +27,6 @@ from .type_conversion import TypeConversion
from .unary import Unary, UnaryType from .unary import Unary, UnaryType
from .unpack import Unpack from .unpack import Unpack
from .length import Length from .length import Length
from .balance import Balance
from .phi import Phi from .phi import Phi
from .phi_callback import PhiCallback from .phi_callback import PhiCallback
from .nop import Nop from .nop import Nop

@ -1,24 +0,0 @@
from slither.core.solidity_types import ElementaryType
from slither.slithir.operations.lvalue import OperationWithLValue
from slither.slithir.utils.utils import is_valid_lvalue, is_valid_rvalue
class Balance(OperationWithLValue):
def __init__(self, value, lvalue):
super().__init__()
assert is_valid_rvalue(value)
assert is_valid_lvalue(lvalue)
self._value = value
self._lvalue = lvalue
lvalue.set_type(ElementaryType("uint256"))
@property
def read(self):
return [self._value]
@property
def value(self):
return self._value
def __str__(self):
return "{} -> BALANCE {}".format(self.lvalue, self.value)

@ -2,6 +2,7 @@ from slither.core.declarations import Contract, Function
from slither.core.declarations.custom_error import CustomError from slither.core.declarations.custom_error import CustomError
from slither.core.declarations.enum import Enum from slither.core.declarations.enum import Enum
from slither.core.declarations.solidity_import_placeholder import SolidityImportPlaceHolder from slither.core.declarations.solidity_import_placeholder import SolidityImportPlaceHolder
from slither.core.solidity_types import ElementaryType
from slither.slithir.operations.lvalue import OperationWithLValue from slither.slithir.operations.lvalue import OperationWithLValue
from slither.slithir.utils.utils import is_valid_rvalue from slither.slithir.utils.utils import is_valid_rvalue
from slither.slithir.variables.constant import Constant from slither.slithir.variables.constant import Constant
@ -21,8 +22,10 @@ class Member(OperationWithLValue):
# f.h(1); # f.h(1);
# } # }
# } # }
# Can be an ElementaryType because of bytes.concat
assert is_valid_rvalue(variable_left) or isinstance( assert is_valid_rvalue(variable_left) or isinstance(
variable_left, (Contract, Enum, Function, CustomError, SolidityImportPlaceHolder) variable_left,
(Contract, Enum, Function, CustomError, SolidityImportPlaceHolder, ElementaryType),
) )
assert isinstance(variable_right, Constant) assert isinstance(variable_right, Constant)

@ -15,7 +15,6 @@ from slither.core.variables.local_variable import LocalVariable
from slither.core.variables.state_variable import StateVariable from slither.core.variables.state_variable import StateVariable
from slither.slithir.operations import ( from slither.slithir.operations import (
Assignment, Assignment,
Balance,
Binary, Binary,
Condition, Condition,
Delete, Delete,
@ -670,10 +669,6 @@ def copy_ir(ir, *instances):
rvalue = get_variable(ir, lambda x: x.rvalue, *instances) rvalue = get_variable(ir, lambda x: x.rvalue, *instances)
variable_return_type = ir.variable_return_type variable_return_type = ir.variable_return_type
return Assignment(lvalue, rvalue, variable_return_type) return Assignment(lvalue, rvalue, variable_return_type)
if isinstance(ir, Balance):
lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
value = get_variable(ir, lambda x: x.value, *instances)
return Balance(value, lvalue)
if isinstance(ir, Binary): if isinstance(ir, Binary):
lvalue = get_variable(ir, lambda x: x.lvalue, *instances) lvalue = get_variable(ir, lambda x: x.lvalue, *instances)
variable_left = get_variable(ir, lambda x: x.variable_left, *instances) variable_left = get_variable(ir, lambda x: x.variable_left, *instances)

@ -23,7 +23,6 @@ from slither.slithir.operations import (
Index, Index,
Member, Member,
Length, Length,
Balance,
Binary, Binary,
Unary, Unary,
Condition, Condition,
@ -150,8 +149,6 @@ def encode_ir(ir): # pylint: disable=too-many-branches
return "member" # .format(ntype(ir._type)) return "member" # .format(ntype(ir._type))
if isinstance(ir, Length): if isinstance(ir, Length):
return "length" return "length"
if isinstance(ir, Balance):
return "balance"
if isinstance(ir, Binary): if isinstance(ir, Binary):
return "binary({})".format(str(ir.type)) return "binary({})".format(str(ir.type))
if isinstance(ir, Unary): if isinstance(ir, Unary):

@ -17,6 +17,7 @@ from slither.core.expressions import (
from slither.core.solidity_types import ArrayType, ElementaryType from slither.core.solidity_types import ArrayType, ElementaryType
from slither.core.solidity_types.type import Type from slither.core.solidity_types.type import Type
from slither.core.variables.local_variable_init_from_tuple import LocalVariableInitFromTuple from slither.core.variables.local_variable_init_from_tuple import LocalVariableInitFromTuple
from slither.core.variables.variable import Variable
from slither.slithir.exceptions import SlithIRError from slither.slithir.exceptions import SlithIRError
from slither.slithir.operations import ( from slither.slithir.operations import (
Assignment, Assignment,
@ -31,6 +32,7 @@ from slither.slithir.operations import (
Unary, Unary,
Unpack, Unpack,
Return, Return,
SolidityCall,
) )
from slither.slithir.tmp_operations.argument import Argument from slither.slithir.tmp_operations.argument import Argument
from slither.slithir.tmp_operations.tmp_call import TmpCall from slither.slithir.tmp_operations.tmp_call import TmpCall
@ -207,12 +209,14 @@ class ExpressionToSlithIR(ExpressionVisitor):
if expression.type in _signed_to_unsigned: if expression.type in _signed_to_unsigned:
new_left = TemporaryVariable(self._node) new_left = TemporaryVariable(self._node)
conv_left = TypeConversion(new_left, left, ElementaryType("int256")) conv_left = TypeConversion(new_left, left, ElementaryType("int256"))
new_left.set_type(ElementaryType("int256"))
conv_left.set_expression(expression) conv_left.set_expression(expression)
self._result.append(conv_left) self._result.append(conv_left)
if expression.type != BinaryOperationType.RIGHT_SHIFT_ARITHMETIC: if expression.type != BinaryOperationType.RIGHT_SHIFT_ARITHMETIC:
new_right = TemporaryVariable(self._node) new_right = TemporaryVariable(self._node)
conv_right = TypeConversion(new_right, right, ElementaryType("int256")) conv_right = TypeConversion(new_right, right, ElementaryType("int256"))
new_right.set_type(ElementaryType("int256"))
conv_right.set_expression(expression) conv_right.set_expression(expression)
self._result.append(conv_right) self._result.append(conv_right)
else: else:
@ -224,6 +228,7 @@ class ExpressionToSlithIR(ExpressionVisitor):
self._result.append(operation) self._result.append(operation)
conv_final = TypeConversion(val, new_final, ElementaryType("uint256")) conv_final = TypeConversion(val, new_final, ElementaryType("uint256"))
val.set_type(ElementaryType("uint256"))
conv_final.set_expression(expression) conv_final.set_expression(expression)
self._result.append(conv_final) self._result.append(conv_final)
else: else:
@ -274,6 +279,7 @@ class ExpressionToSlithIR(ExpressionVisitor):
elif called.name == "selfbalance()": elif called.name == "selfbalance()":
val = TemporaryVariable(self._node) val = TemporaryVariable(self._node)
var = TypeConversion(val, SolidityVariable("this"), ElementaryType("address")) var = TypeConversion(val, SolidityVariable("this"), ElementaryType("address"))
val.set_type(ElementaryType("address"))
self._result.append(var) self._result.append(var)
val1 = ReferenceVariable(self._node) val1 = ReferenceVariable(self._node)
@ -283,6 +289,7 @@ class ExpressionToSlithIR(ExpressionVisitor):
elif called.name == "address()": elif called.name == "address()":
val = TemporaryVariable(self._node) val = TemporaryVariable(self._node)
var = TypeConversion(val, SolidityVariable("this"), ElementaryType("address")) var = TypeConversion(val, SolidityVariable("this"), ElementaryType("address"))
val.set_type(ElementaryType("address"))
self._result.append(var) self._result.append(var)
set_val(expression, val) set_val(expression, val)
elif called.name == "callvalue()": elif called.name == "callvalue()":
@ -385,6 +392,27 @@ class ExpressionToSlithIR(ExpressionVisitor):
set_val(expression, val) set_val(expression, val)
return return
# This does not support solidity 0.4 contract_name.balance
if (
isinstance(expr, Variable)
and expr.type == ElementaryType("address")
and expression.member_name in ["balance", "code", "codehash"]
):
val = TemporaryVariable(self._node)
name = expression.member_name + "(address)"
sol_func = SolidityFunction(name)
s = SolidityCall(
sol_func,
1,
val,
sol_func.return_type,
)
s.set_expression(expression)
s.arguments.append(expr)
self._result.append(s)
set_val(expression, val)
return
val = ReferenceVariable(self._node) val = ReferenceVariable(self._node)
member = Member(expr, Constant(expression.member_name), val) member = Member(expr, Constant(expression.member_name), val)
member.set_expression(expression) member.set_expression(expression)
@ -432,6 +460,7 @@ class ExpressionToSlithIR(ExpressionVisitor):
expr = get(expression.expression) expr = get(expression.expression)
val = TemporaryVariable(self._node) val = TemporaryVariable(self._node)
operation = TypeConversion(val, expr, expression.type) operation = TypeConversion(val, expr, expression.type)
val.set_type(expression.type)
operation.set_expression(expression) operation.set_expression(expression)
self._result.append(operation) self._result.append(operation)
set_val(expression, val) set_val(expression, val)

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save