Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix if instead ifloop bug #2069

Open
wants to merge 15 commits into
base: dev
Choose a base branch
from
  •  
  •  
  •  
84 changes: 77 additions & 7 deletions slither/solc_parsing/declarations/function.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@
FunctionType,
)
from slither.core.declarations.function_contract import FunctionContract
from slither.core.expressions import AssignmentOperation
from slither.core.expressions import AssignmentOperation, AssignmentOperationType, Identifier
from slither.core.source_mapping.source_mapping import Source
from slither.core.variables.local_variable import LocalVariable
from slither.core.variables.local_variable_init_from_tuple import LocalVariableInitFromTuple
from slither.core.solidity_types.elementary_type import ElementaryType
from slither.solc_parsing.cfg.node import NodeSolc
from slither.solc_parsing.declarations.caller_context import CallerContextExpression
from slither.solc_parsing.exceptions import ParsingError
Expand Down Expand Up @@ -46,8 +47,8 @@ def link_underlying_nodes(node1: NodeSolc, node2: NodeSolc):


class FunctionSolc(CallerContextExpression):

# elems = [(type, name)]
temp_var_num: int = 0

def __init__(
self,
Expand Down Expand Up @@ -598,7 +599,6 @@ def _parse_for(self, statement: Dict, node: NodeSolc, scope: Scope) -> NodeSolc:
return node_endLoop

def _parse_dowhile(self, do_while_statement: Dict, node: NodeSolc, scope: Scope) -> NodeSolc:

node_startDoWhile = self._new_node(NodeType.STARTLOOP, do_while_statement["src"], scope)
condition_scope = Scope(scope.is_checked, False, scope)

Expand Down Expand Up @@ -1101,7 +1101,6 @@ def _parse_unchecked_block(self, block: Dict, node: NodeSolc, scope):
return node

def _parse_cfg(self, cfg: Dict) -> None:

assert cfg[self.get_key()] == "Block"

node = self._new_node(NodeType.ENTRYPOINT, cfg["src"], self.underlying_function)
Expand Down Expand Up @@ -1208,7 +1207,6 @@ def _fix_catch(self, node: Node, end_node: Node, visited: Set[Node]) -> None:
self._fix_catch(son, end_node, visited)

def _add_param(self, param: Dict, initialized: bool = False) -> LocalVariableSolc:

local_var = LocalVariable()
local_var.set_function(self._function)
local_var.set_offset(param["src"], self._function.compilation_unit)
Expand All @@ -1228,7 +1226,6 @@ def _add_param(self, param: Dict, initialized: bool = False) -> LocalVariableSol
return local_var_parser

def _add_param_init_tuple(self, statement: Dict, index: int) -> LocalVariableInitFromTupleSolc:

local_var = LocalVariableInitFromTuple()
local_var.set_function(self._function)
local_var.set_offset(statement["src"], self._function.compilation_unit)
Expand All @@ -1254,7 +1251,6 @@ def _parse_params(self, params: Dict):
self._function.add_parameters(local_var.underlying_variable)

def _parse_returns(self, returns: Dict):

assert returns[self.get_key()] == "ParameterList"

self._function.returns_src().set_offset(returns["src"], self._function.compilation_unit)
Expand Down Expand Up @@ -1399,6 +1395,75 @@ def _remove_alone_endif(self) -> None:
###################################################################################
###################################################################################

def __make_temporary_variable_declaration_node_from_condition(
self, node: Node, temp_var: Optional[LocalVariable] = None
) -> (Node, LocalVariable):
temp_var_node_parser = self._new_node(NodeType.VARIABLE, node.source_mapping, node.scope)
temp_var_node = temp_var_node_parser.underlying_node
if temp_var is None:
FunctionSolc.temp_var_num += 1
temp_var = LocalVariable()
temp_var.name = f"temp-var-{FunctionSolc.temp_var_num}"
temp_var.type = ElementaryType("bool")
temp_var.initialized = True
temp_var.set_location("default")
temp_var.set_function(node.function)
temp_var_node.add_expression(
AssignmentOperation(
Identifier(temp_var), node.expression, AssignmentOperationType.ASSIGN, None
)
)
temp_var_node.add_variable_declaration(temp_var)
return (temp_var_node, temp_var)

def __link_node_immediately_before(
self, new_node: Node, node_in_cfg: Node, node_not_to_be_detached: Optional[Node] = None
) -> None:
for father in node_in_cfg.fathers:
if father == node_not_to_be_detached:
continue
father.replace_son(node_in_cfg, new_node)
node_in_cfg.remove_father(father)
new_node.add_father(father)
link_nodes(new_node, node_in_cfg)

def __find_start_loop_in_nodes_fathers(self, node: Node) -> Optional[Node]:
begin_loop_node: Optional[Node] = None
for father in node.fathers:
if father.type == NodeType.STARTLOOP:
begin_loop_node = father
break
return begin_loop_node

def __inject_condition_expression_from_conditional_node(self, node: Node) -> Node:
temp_var_node, temp_var = self.__make_temporary_variable_declaration_node_from_condition(
node
)
if node.type == NodeType.IF:
self.__link_node_immediately_before(temp_var_node, node)
elif node.type == NodeType.IFLOOP:
if_loop_node = node
begin_loop_node: Optional[Node] = self.__find_start_loop_in_nodes_fathers(if_loop_node)
if begin_loop_node: # if BEGIN_LOOP is IF_LOOP's father, IF_LOOP represents `while`
temp_var_node_pre_loop = temp_var_node
(
temp_var_node_during_loop,
_,
) = self.__make_temporary_variable_declaration_node_from_condition(
if_loop_node, temp_var
)
self.__link_node_immediately_before(
temp_var_node_during_loop, if_loop_node, begin_loop_node
)
self.__link_node_immediately_before(temp_var_node_pre_loop, begin_loop_node)
else:
self.__link_node_immediately_before(temp_var_node, if_loop_node)
else:
raise TypeError(f"Unknown conditional type {node.type}")

node.add_expression(Identifier(temp_var), bypass_verif_empty=True)
return temp_var_node

def _rewrite_ternary_as_if_else(self) -> bool:
ternary_found = True
updated = False
Expand All @@ -1407,6 +1472,11 @@ def _rewrite_ternary_as_if_else(self) -> bool:
for node in self._node_to_nodesolc:
has_cond = HasConditional(node.expression)
if has_cond.result():
if node.is_conditional():
temp_var_node = self.__inject_condition_expression_from_conditional_node(
node
)
node = temp_var_node # goes back by new cfg
st = SplitTernaryExpression(node.expression)
condition = st.condition
if not condition:
Expand Down
20 changes: 20 additions & 0 deletions tests/e2e/solc_parsing/test_ast_parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,10 @@ def make_version(minor: int, patch_min: int, patch_max: int) -> List[str]:
"if-all.sol",
ALL_VERSIONS,
),
Test(
"if-with-ternary-condition-all.sol",
ALL_VERSIONS,
),
Test(
"modifier-all.sol",
VERSIONS_04 + VERSIONS_05 + VERSIONS_06,
Expand Down Expand Up @@ -331,6 +335,10 @@ def make_version(minor: int, patch_min: int, patch_max: int) -> List[str]:
"dowhile-0.4.5.sol",
make_version(4, 5, 9) + VERSIONS_05 + VERSIONS_06 + VERSIONS_07 + VERSIONS_08,
),
Test(
"dowhile-with-ternary-condition-0.4.5.sol",
make_version(4, 5, 9) + VERSIONS_05 + VERSIONS_06 + VERSIONS_07 + VERSIONS_08,
),
Test(
"custom_error-0.4.0.sol",
ALL_VERSIONS,
Expand Down Expand Up @@ -367,6 +375,10 @@ def make_version(minor: int, patch_min: int, patch_max: int) -> List[str]:
"for-all.sol",
ALL_VERSIONS,
),
Test(
"for-with-ternary-condition-all.sol",
ALL_VERSIONS,
),
Test("trycatch-0.4.0.sol", VERSIONS_04 + VERSIONS_05),
# TODO: legacy failing
Test(
Expand Down Expand Up @@ -412,6 +424,14 @@ def make_version(minor: int, patch_min: int, patch_max: int) -> List[str]:
"while-all.sol",
ALL_VERSIONS,
),
Test(
"while-with-ternary-condition-all.sol",
ALL_VERSIONS,
),
Test(
"nested-while-with-ternary-condition-all.sol",
ALL_VERSIONS,
),
Test(
"complex_imports/import_free/Caller.sol",
["0.8.2"],
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading
Loading