Skip to content

Commit

Permalink
Fix+Test: *(&x)
Browse files Browse the repository at this point in the history
  • Loading branch information
NeoQuix committed Jun 11, 2024
1 parent c614de9 commit 3ea3a9b
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 4 deletions.
8 changes: 4 additions & 4 deletions decompiler/pipeline/commons/expressionpropagationcommons.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
"""
Expand Down Expand Up @@ -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):
Expand Down
38 changes: 38 additions & 0 deletions tests/pipeline/dataflowanalysis/test_expression_propagation_mem.py
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down

0 comments on commit 3ea3a9b

Please sign in to comment.