summaryrefslogtreecommitdiff
path: root/lang
diff options
context:
space:
mode:
authorMark Rowe <mark@vector35.com>2025-07-15 22:51:36 -0700
committerMark Rowe <mark@vector35.com>2025-07-16 15:16:09 -0700
commit400c215f98115b1a05ef2f9bff01f0bef4bb29ef (patch)
tree9a724de0f1dd5ccd33fce890e5fad45484fb2f72 /lang
parente3b8be66fd04e7ef6430ed4cf677a6ef73e19cc5 (diff)
[PseudoC] Fix handling of struct field accesses at offset 0
Diffstat (limited to 'lang')
-rw-r--r--lang/c/pseudoc.cpp67
1 files changed, 39 insertions, 28 deletions
diff --git a/lang/c/pseudoc.cpp b/lang/c/pseudoc.cpp
index a091677d..b7ced55a 100644
--- a/lang/c/pseudoc.cpp
+++ b/lang/c/pseudoc.cpp
@@ -2569,7 +2569,7 @@ void PseudoCFunction::GetExprTextInternal(const HighLevelILInstruction& instr, H
if (type && (type->GetClass() == NamedTypeReferenceClass))
type = GetFunction()->GetView()->GetTypeByRef(type->GetNamedTypeReference());
- bool derefOffset = false;
+ // Handle structure member access
if (type && (type->GetClass() == StructureTypeClass))
{
std::optional<size_t> memberIndexHint;
@@ -2610,51 +2610,62 @@ void PseudoCFunction::GetExprTextInternal(const HighLevelILInstruction& instr, H
memberIndexHint)
return;
}
- else if (type && (type->GetClass() == StructureTypeClass))
+
+ // For non-struct types or when struct member resolution fails,
+ // render as pointer arithmetic: *[(type*)]([(char*)]expr[ + offset])
+ bool hasOffset = offset != 0;
+ bool needsOuterParens = precedence > UnaryOperatorPrecedence;
+ bool showTypeCasts = !settings || settings->IsOptionSet(ShowTypeCasts);
+
+ if (needsOuterParens)
+ tokens.AppendOpenParen();
+
+ tokens.Append(OperationToken, "*");
+
+ // Skip the outer cast if we're dereferencing a single byte and are
+ // already casting to char* for the pointer arithmetic
+ bool skipOuterCast = hasOffset && instr.size == 1;
+ if (showTypeCasts && !skipOuterCast)
{
- derefOffset = true;
+ tokens.AppendOpenParen();
+ AppendSizeToken(hasOffset && type ? srcExpr.size : instr.size, true, tokens);
+ tokens.Append(TextToken, "*");
+ tokens.AppendCloseParen();
}
- if (derefOffset || offset != 0)
+ if (hasOffset)
{
- bool parens = precedence > UnaryOperatorPrecedence;
- if (parens)
- tokens.AppendOpenParen();
-
- tokens.Append(OperationToken, "*");
- if (!settings || settings->IsOptionSet(ShowTypeCasts))
- {
- tokens.AppendOpenParen();
- AppendSizeToken(!derefOffset ? srcExpr.size : instr.size, true, tokens);
- tokens.Append(TextToken, "*");
- tokens.AppendCloseParen();
- }
tokens.AppendOpenParen();
- if (!settings || settings->IsOptionSet(ShowTypeCasts))
+ if (showTypeCasts)
{
tokens.AppendOpenParen();
tokens.Append(TypeNameToken, "char");
tokens.Append(TextToken, "*");
tokens.AppendCloseParen();
}
+ }
- if (srcExpr.operation == HLIL_CONST_PTR)
- {
- const auto constant = srcExpr.GetConstant<HLIL_CONST_PTR>();
- tokens.AppendPointerTextToken(srcExpr, constant, settings, DisplaySymbolOnly, precedence);
- }
- else
- {
- GetExprTextInternal(srcExpr, tokens, settings, AddOperatorPrecedence);
- }
+ if (srcExpr.operation == HLIL_CONST_PTR)
+ {
+ const auto constant = srcExpr.GetConstant<HLIL_CONST_PTR>();
+ tokens.AppendPointerTextToken(srcExpr, constant, settings, DisplaySymbolOnly, precedence);
+ }
+ else
+ {
+ GetExprTextInternal(srcExpr, tokens, settings,
+ hasOffset ? AddOperatorPrecedence : UnaryOperatorPrecedence);
+ }
+ if (hasOffset)
+ {
tokens.Append(OperationToken, " + ");
tokens.AppendIntegerTextToken(instr, offset, instr.size);
tokens.AppendCloseParen();
- if (parens)
- tokens.AppendCloseParen();
}
+ if (needsOuterParens)
+ tokens.AppendCloseParen();
+
if (statement)
tokens.AppendSemicolon();
}();