Skip to content

Commit

Permalink
Fix escaping of string literals (#428)
Browse files Browse the repository at this point in the history
* Fix string literal escaping

* Run Black obfuscation

* Revert _format_string_literal back

* Revert _format_string_literal back 2
  • Loading branch information
rihi authored Aug 1, 2024
1 parent 3ed0094 commit ad2f8a3
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 4 deletions.
10 changes: 7 additions & 3 deletions decompiler/backend/cexpressiongenerator.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,10 @@ class CExpressionGenerator(DataflowObjectVisitorInterface):
# OperationType.adc: "adc",
}

ESCAPE_TABLE = str.maketrans(
{"\\": r"\\", '"': r"\"", "'": r"\'", "\n": r"\n", "\r": r"\r", "\t": r"\t", "\v": r"\v", "\b": r"\b", "\f": r"\f", "\0": r"\0"}
)

def visit_unknown_expression(self, expr: expressions.UnknownExpression) -> str:
"""Return the error message for this UnknownExpression."""
return expr.msg
Expand Down Expand Up @@ -197,16 +201,16 @@ def visit_constant_composition(self, expr: expressions.ConstantComposition):
"""Visit a Constant Array."""
match expr.type.type:
case CustomType(text="wchar16") | CustomType(text="wchar32"):
val = "".join([x.value for x in expr.value])
val = "".join([x.value for x in expr.value]).translate(self.ESCAPE_TABLE)
return f'L"{val}"' if len(val) <= MAX_GLOBAL_INIT_LENGTH else f'L"{val[:MAX_GLOBAL_INIT_LENGTH]}..."'
case Integer(size=8, signed=False):
val = "".join([f"\\x{x.value:02X}" for x in expr.value][:MAX_GLOBAL_INIT_LENGTH])
return f'"{val}"' if len(val) <= MAX_GLOBAL_INIT_LENGTH else f'"{val[:MAX_GLOBAL_INIT_LENGTH]}..."'
case Integer(8):
val = "".join([x.value for x in expr.value][:MAX_GLOBAL_INIT_LENGTH])
val = "".join([x.value for x in expr.value][:MAX_GLOBAL_INIT_LENGTH]).translate(self.ESCAPE_TABLE)
return f'"{val}"' if len(val) <= MAX_GLOBAL_INIT_LENGTH else f'"{val[:MAX_GLOBAL_INIT_LENGTH]}..."'
case _:
return f'{", ".join([self.visit(x) for x in expr.value])}' # Todo: Should we print every member? Could get pretty big
return f'{", ".join([self.visit(x) for x in expr.value]).translate(self.ESCAPE_TABLE)}' # Todo: Should we print every member? Could get pretty big

def visit_variable(self, expr: expressions.Variable) -> str:
"""Return a string representation of the variable."""
Expand Down
6 changes: 5 additions & 1 deletion decompiler/backend/codevisitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,11 @@ def _condition_string(self, condition: ConditionVar) -> str:
def _format_integer_literal(self, type_info: Integer, value: int) -> str:
"""Format the integer based on the codegenerators settings."""

byte_format_handler = {"char": lambda x: f"'{chr(x)}'", "hex": lambda x: f"{hex(x)}", "dec": lambda x: f"{x}"}
byte_format_handler = {
"char": lambda x: f"'{chr(x).translate(self.ESCAPE_TABLE)}'",
"hex": lambda x: f"{hex(x)}",
"dec": lambda x: f"{x}",
}
if self._possibly_char_in_ascii_range(type_info, value):
if value_handler := byte_format_handler.get(self._byte_format, None):
if hint_handler := byte_format_handler.get(self._byte_format_hint, None):
Expand Down

0 comments on commit ad2f8a3

Please sign in to comment.