diff --git a/lang/c/pseudoc.cpp b/lang/c/pseudoc.cpp index a091677db..b7ced55a2 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 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(); - tokens.AppendPointerTextToken(srcExpr, constant, settings, DisplaySymbolOnly, precedence); - } - else - { - GetExprTextInternal(srcExpr, tokens, settings, AddOperatorPrecedence); - } + if (srcExpr.operation == HLIL_CONST_PTR) + { + const auto constant = srcExpr.GetConstant(); + 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(); }();