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

[ValueError@identity_elimination.py:278] ValueError: There are at least two definitions in the identity group var_58#0 = var_58#0 + (&(var_58#0)), var_58#0. #413

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
75 changes: 75 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,81 @@ 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 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)
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_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))
Expand Down
Loading