From 3c2ceaee81b8ad7d340cfe8ac86abc2031bf3dc9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 7 Dec 2023 08:20:30 +0100 Subject: [PATCH] [CExpressionGenerator] MemberAccess/Call on complex expression is missing parentheses (#372) * Create draft PR for #361 * Fix incorrect braces on call/memberaccess --------- Co-authored-by: rihi Co-authored-by: rihi <19492038+rihi@users.noreply.github.com> --- decompiler/backend/cexpressiongenerator.py | 11 +++++------ tests/backend/test_codegenerator.py | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/decompiler/backend/cexpressiongenerator.py b/decompiler/backend/cexpressiongenerator.py index 8ce03e778..5f0775949 100644 --- a/decompiler/backend/cexpressiongenerator.py +++ b/decompiler/backend/cexpressiongenerator.py @@ -167,10 +167,10 @@ def visit_list_operation(self, op: operations.ListOperation) -> str: def visit_unary_operation(self, op: operations.UnaryOperation) -> str: """Return a string representation of the given unary operation (e.g. !a or &a).""" + operand = self._visit_bracketed(op.operand) if self._has_lower_precedence(op.operand, op) else self.visit(op.operand) if isinstance(op, MemberAccess): operator_str = "->" if isinstance(op.struct_variable.type, Pointer) else self.C_SYNTAX[op.operation] - return f"{self.visit(op.struct_variable)}{operator_str}{op.member_name}" - operand = self._visit_bracketed(op.operand) if self._has_lower_precedence(op.operand, op) else self.visit(op.operand) + return f"{operand}{operator_str}{op.member_name}" if op.operation == OperationType.cast and op.contraction: return f"({int(op.type.size / 8)}: ){operand}" if op.operation == OperationType.cast: @@ -209,10 +209,9 @@ def visit_call(self, op: operations.Call) -> str: Generic labels starting with 'arg' e.g. 'arg1', 'arg2' are being filtered. Additionally we filter ellipsis argument '...' that is lifted from type string. """ - func_name = self.visit(op.function) - if isinstance(op.function, expressions.Constant): - func_name = func_name.strip('"') - output = f"{func_name}(" + func_expr_str = self._visit_bracketed(op.function) if self._has_lower_precedence(op.function, op) else self.visit(op.function) + + output = f"{func_expr_str}(" if op.meta_data is not None: parameter_names = op.meta_data.get("param_names", []) is_tailcall = op.meta_data.get("is_tailcall") diff --git a/tests/backend/test_codegenerator.py b/tests/backend/test_codegenerator.py index caaade2c9..234c049a6 100644 --- a/tests/backend/test_codegenerator.py +++ b/tests/backend/test_codegenerator.py @@ -784,6 +784,21 @@ def test_array_element_access_aggressive(self, operation, result): ), "ptr->x->z->w", ), + ( + MemberAccess( + offset=0, + member_name="x", + operands=[ + BinaryOperation( + OperationType.plus, + [Variable("ptr", Pointer(Integer.int32_t())), Constant(1, Integer.int32_t())], + Pointer(Integer.int32_t()), + ) + ], + vartype=Integer.int32_t(), + ), + "(ptr + 1)->x", + ), ], ) def test_member_access(self, operation, result): @@ -816,6 +831,7 @@ def test_member_access(self, operation, result): ), "foo(/* param1 */ x, /* param2 */ y, z)", ), + (Assignment(ListOperation([]), Call(UnaryOperation(OperationType.dereference, [var_x]), [])), "(*x)()"), ], ) def test_call(self, expr, result):