From c614de94f9c372173940b4dd3b12ce39c79ce120 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 5 Jun 2024 15:37:29 +0000 Subject: [PATCH 1/3] Create draft PR for #390 From 3ea3a9b3060f1ee6dc8faeaad9537cd44e0d7132 Mon Sep 17 00:00:00 2001 From: Spartak Ehrlich Date: Tue, 11 Jun 2024 12:01:46 +0200 Subject: [PATCH 2/3] Fix+Test: *(&x) --- .../commons/expressionpropagationcommons.py | 8 ++-- .../test_expression_propagation_mem.py | 38 +++++++++++++++++++ 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/decompiler/pipeline/commons/expressionpropagationcommons.py b/decompiler/pipeline/commons/expressionpropagationcommons.py index 36c57c14b..c9e95f4ff 100644 --- a/decompiler/pipeline/commons/expressionpropagationcommons.py +++ b/decompiler/pipeline/commons/expressionpropagationcommons.py @@ -225,8 +225,9 @@ def _is_address_into_dereference(self, definition: Assignment, target: Instructi if self._is_address(definition.value): for subexpr in target: for sub in self._find_subexpressions(subexpr): - if self._is_dereference(sub) and sub.operand == definition.destination: + if self._is_dereference(sub) and sub.operand in definition.definitions: return True + return False def _contains_aliased_variables(self, definition: Assignment) -> bool: """ @@ -326,14 +327,13 @@ def _has_any_of_dangerous_uses_between_definition_and_target( def _get_dangerous_uses_of_variable_address(self, var: Variable) -> Set[Instruction]: """ Dangerous use of & of x is func(&x) cause it can potentially modify x. - *(&x) could also do the job but I consider it to be too exotic so that we could get such instruction from Binary Ninja - If it happens we can handle it later. + Another case is an Assignment where the left side is *(&). :param var: aliased variable :return: set of function call assignments that take &var as parameter """ dangerous_uses = set() for use in self._use_map.get(var): - if not self._is_call_assignment(use): + if not self._is_call_assignment(use) and not (isinstance(use, Assignment) and self._is_dereference(use.destination)): continue for subexpr in self._find_subexpressions(use): if self._is_address(subexpr): diff --git a/tests/pipeline/dataflowanalysis/test_expression_propagation_mem.py b/tests/pipeline/dataflowanalysis/test_expression_propagation_mem.py index 5e6f4d124..b4c0fa0d0 100644 --- a/tests/pipeline/dataflowanalysis/test_expression_propagation_mem.py +++ b/tests/pipeline/dataflowanalysis/test_expression_propagation_mem.py @@ -1676,6 +1676,44 @@ def test_correct_propagation_relation(): ] +def test_address_into_dereference(): + """ + Test with cast in destination (x#0 stays the same type) + +---------------------+ + | 0. | + | (long) x#0 = &(x#1) | + | *(x#0) = x#0 | + +---------------------+ + + +---------------------+ + | 0. | + | (long) x#0 = &(x#1) | + | *(x#0) = x#0 | + +---------------------+ + """ + input_cfg, output_cfg = graphs_addr_into_deref() + _run_expression_propagation(input_cfg) + assert _graphs_equal(input_cfg, output_cfg) + + +def graphs_addr_into_deref(): + x = vars("x", 2) + c = const(10) + in_n0 = BasicBlock( + 0, + [_assign(_cast(int64, x[0]), _addr(x[1])), _assign(_deref(x[0]), x[0])], + ) + in_cfg = ControlFlowGraph() + in_cfg.add_node(in_n0) + out_n0 = BasicBlock( + 0, + [_assign(_cast(int64, x[0]), _addr(x[1])), _assign(_deref(x[0]), x[0])], + ) + out_cfg = ControlFlowGraph() + out_cfg.add_node(out_n0) + return in_cfg, out_cfg + + def graphs_with_no_propagation_of_contraction_address_assignment(): x = vars("x", 3) ptr = vars("ptr", 1, type=Pointer(int32)) From e60a8f869829854bb777573b1a0d1d626d9789fa Mon Sep 17 00:00:00 2001 From: Spartak Ehrlich Date: Wed, 19 Jun 2024 10:05:06 +0200 Subject: [PATCH 3/3] Mult. def test --- .../test_expression_propagation_mem.py | 39 ++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/tests/pipeline/dataflowanalysis/test_expression_propagation_mem.py b/tests/pipeline/dataflowanalysis/test_expression_propagation_mem.py index b4c0fa0d0..a288538b5 100644 --- a/tests/pipeline/dataflowanalysis/test_expression_propagation_mem.py +++ b/tests/pipeline/dataflowanalysis/test_expression_propagation_mem.py @@ -1696,9 +1696,28 @@ def test_address_into_dereference(): assert _graphs_equal(input_cfg, output_cfg) +def test_address_into_dereference_with_multiple_defs(): + """ + Extended test of above where we have two definitions (as a ListOp). + +---------------------+ + | 0. | + | (long) x#1 = &(x#0) | + | *(x#1),y#0 = x#1 | + +---------------------+ + + +---------------------+ + | 0. | + | (long) x#1 = &(x#0) | + | *(x#1),y#0 = x#1 | + +---------------------+ + """ + input_cfg, output_cfg = graphs_addr_into_deref_multiple_defs() + _run_expression_propagation(input_cfg) + assert _graphs_equal(input_cfg, output_cfg) + + def graphs_addr_into_deref(): x = vars("x", 2) - c = const(10) in_n0 = BasicBlock( 0, [_assign(_cast(int64, x[0]), _addr(x[1])), _assign(_deref(x[0]), x[0])], @@ -1714,6 +1733,24 @@ def graphs_addr_into_deref(): return in_cfg, out_cfg +def graphs_addr_into_deref_multiple_defs(): + x = vars("x", 2) + y = vars("y", 1) + in_n0 = BasicBlock( + 0, + [_assign(_cast(int64, x[1]), _addr(x[0])), _assign(ListOperation([_deref(x[1]), y[0]]), x[1])], + ) + in_cfg = ControlFlowGraph() + in_cfg.add_node(in_n0) + out_n0 = BasicBlock( + 0, + [_assign(_cast(int64, x[1]), _addr(x[0])), _assign(ListOperation([_deref(x[1]), y[0]]), x[1])], + ) + out_cfg = ControlFlowGraph() + out_cfg.add_node(out_n0) + return in_cfg, out_cfg + + def graphs_with_no_propagation_of_contraction_address_assignment(): x = vars("x", 3) ptr = vars("ptr", 1, type=Pointer(int32))