dissect.cstruct
dissect.cstruct copied to clipboard
Ignore casts when evaluating #defines
For example:
#define A ((unsigned long) 1)
#define B ((unsigned long) 2)
#define C (A | B)
causes A, B and C to have string values like "(A | B)" instead of the numeric values.
This looks very fixable. Probably requires dealing with casts in the expression parser though.
@sMezaOrellana can you perhaps recommend the best way to add this to your parser?
I will try to have a proper look in the coming days. In order implement or deal with type-casting it will require changing the evaluate function.
def evaluate(self, context: Optional[dict[str, int]] = None) -> int:
"""Evaluates an expression using a Shunting-Yard implementation."""
...
while i < len(tmp_expression):
current_token = tmp_expression[i]
...
elif current_token == "sizeof":
if len(tmp_expression) < i + 3 or (tmp_expression[i + 1] != "(" or tmp_expression[i + 3] != ")"):
raise ExpressionParserError("Invalid sizeof operation")
self.queue.append(len(self.cstruct.resolve(tmp_expression[i + 2])))
i += 3
...
elif current_token == "(":
if i > 0:
previous_token = tmp_expression[i - 1]
if self.is_number(previous_token):
raise ExpressionParserError(
f"Parser expected sizeof or an arethmethic operator instead got: '{previous_token}'"
)
self.stack.append(current_token)
elif current_token == ")":
if i > 0:
previous_token = tmp_expression[i - 1]
if previous_token == "(":
raise ExpressionParserError(
f"Parser expected an expression, instead received empty parenthesis. Index: {i}"
)
...
while len(self.stack) != 0:
if self.stack[-1] == "(":
raise ExpressionParserError("Invalid expression")
self.evaluate_exp()
return self.queue[0]
Take for example ((unsigned long) 10) this is something like an expression with the left-hand side being (unsigned long) and the right-hand side being 10, there is no explicit operator.
This could simply evaluate to 10. In practise a simple solution would be to change the case where elif current_token == "(": and elif current_token == ")":. If whatever is between ( and ) is a casting expression just skip over it. It's not very pretty but it would work. In order to actually implement casting we would need to extend the parser, to support evaluating the casting expression.
Does cstruct implement casting?
I hope this helps. And will look at this properly sometime this week.
We don't really support casting, no. The new v4 (#35) should make this easier/possible, but it's not a feature as of yet.