From 5319654922a57603e880af24a847553952d3a0be Mon Sep 17 00:00:00 2001 From: Josselin Date: Wed, 28 Apr 2021 14:02:10 +0200 Subject: [PATCH] Add unchecked block information + add checked arithmetic info --- slither/slithir/operations/binary.py | 5 ++++ slither/solc_parsing/declarations/function.py | 27 ++++++++++++++++--- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/slither/slithir/operations/binary.py b/slither/slithir/operations/binary.py index c3464564e..66f0b965b 100644 --- a/slither/slithir/operations/binary.py +++ b/slither/slithir/operations/binary.py @@ -88,6 +88,9 @@ class BinaryType(Enum): raise SlithIRError("get_type: Unknown operation type {})".format(operation_type)) + def can_be_checked_for_overflow(self): + return self in [BinaryType.POWER, BinaryType.MULTIPLICATION, BinaryType.MODULO, BinaryType.ADDITION, BinaryType.SUBTRACTION, BinaryType.DIVISION] + def __str__(self): # pylint: disable=too-many-branches if self == BinaryType.POWER: return "**" @@ -168,6 +171,8 @@ class Binary(OperationWithLValue): @property def type_str(self): + if self.node.scope.is_checked and self._type.can_be_checked_for_overflow(): + return '(c)' + str(self._type) return str(self._type) def __str__(self): diff --git a/slither/solc_parsing/declarations/function.py b/slither/solc_parsing/declarations/function.py index eb6f63bd4..57d25b58c 100644 --- a/slither/solc_parsing/declarations/function.py +++ b/slither/solc_parsing/declarations/function.py @@ -881,6 +881,8 @@ class FunctionSolc: node = self._parse_for(statement, node) elif name == "Block": node = self._parse_block(statement, node) + elif name == "UncheckedBlock": + node = self._parse_unchecked_block(statement, node) elif name == "InlineAssembly": # Added with solc 0.6 - the yul code is an AST if "AST" in statement and not self.compilation_unit.core.skip_assembly: @@ -965,7 +967,7 @@ class FunctionSolc: return node - def _parse_block(self, block: Dict, node: NodeSolc): + def _parse_block(self, block: Dict, node: NodeSolc, check_arithmetic:bool = False): """ Return: Node @@ -977,7 +979,25 @@ class FunctionSolc: else: statements = block[self.get_children("children")] - new_scope = Scope(node.underlying_node.scope.is_checked, False, node.underlying_node.scope) + check_arithmetic = check_arithmetic | node.underlying_node.scope.is_checked + new_scope = Scope(check_arithmetic, False, node.underlying_node.scope) + for statement in statements: + node = self._parse_statement(statement, node, new_scope) + return node + + def _parse_unchecked_block(self, block: Dict, node: NodeSolc): + """ + Return: + Node + """ + assert block[self.get_key()] == "UncheckedBlock" + + if self.is_compact_ast: + statements = block["statements"] + else: + statements = block[self.get_children("children")] + + new_scope = Scope(False, False, node.underlying_node.scope) for statement in statements: node = self._parse_statement(statement, node, new_scope) return node @@ -998,7 +1018,8 @@ class FunctionSolc: self._function.is_empty = True else: self._function.is_empty = False - self._parse_block(cfg, node) + check_arithmetic = self.compilation_unit.solc_version >= "0.8.0" + self._parse_block(cfg, node, check_arithmetic=check_arithmetic) self._remove_incorrect_edges() self._remove_alone_endif()