Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Misdecompilation with overlapping reads and writes #6499

Open
ave9858 opened this issue May 11, 2024 · 0 comments
Open

Misdecompilation with overlapping reads and writes #6499

ave9858 opened this issue May 11, 2024 · 0 comments
Assignees
Labels
Feature: Decompiler Status: Triage Information is being gathered

Comments

@ave9858
Copy link

ave9858 commented May 11, 2024

Describe the bug
Certain functions when decompiled will produce code that doesn't match the original behavior of the function due to a read being re-ordered to after a multi-byte write has overridden the source value. This seems to happen only when the write and read don't happen at the exact same address. For example, the compiled code

int test_decomp(unsigned char *a)
{
    unsigned char num = a[4];
    *(unsigned long long*)&a[2] = 0;
    return num == 42;
}

will decompile to

int __cdecl test_decomp(uchar *param_1)

{
  uint local_14;
  
  *(undefined8 *)(param_1 + 2) = 0;
  local_14 = (uint)(param_1[4] == '*');
  return local_14;
}

which will always return 0 due to the first line overriding the value of param_1[4].

To Reproduce
Steps to reproduce the behavior:
I've attached a source file that when compiled and decompiled shows the issue. It was tested by building with Visual Studio/MSVC, targeting Windows x64, and importing the built exe into Ghidra. Optimizations must be disabled in this example so the function doesn't get removed from the final binary. To confirm the behavior is different, the decompiled C can be copied into the original program which will cause the output to change.

Expected behavior
The decompiled source should preserve the order of reads and writes in all cases where it is significant, for example

int __cdecl test_decomp(uchar *param_1)
{
  uchar uVar1;
  uint local_14;
  
  uVar1 = param_1[4];
  *(undefined8 *)(param_1 + 2) = 0;
  local_14 = (uint)(uVar1 == '*');
  return local_14;
}

Screenshots
image

Attachments
I've attached the source code I used to test this issue.
test.c.txt

Environment (please complete the following information):

  • OS: Microsoft Windows [Version 10.0.19044.4291]
  • Java Version: 17.0.11
  • Ghidra Version: 11.0.3
  • Ghidra Origin: official GitHub
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature: Decompiler Status: Triage Information is being gathered
Projects
None yet
Development

No branches or pull requests

3 participants