ghidra
ghidra copied to clipboard
Decompiler: variable-size array on stack yields invalid decompilation results
Describe the bug Variable-size array introduces junk assignment instructions in the code; functions taking it as an argument are called with incorrect number of arguments (and it is impossible to remove extra arg by providing signature override).
To Reproduce Steps to reproduce the behavior:
- Create a test program:
void memcopy(char *dst, const char *src, int len) {
for (int i = 0; i < len; i++)
dst[i] = src[i];
}
int test(const char *value, int len) {
char buffer[len];
memcopy(buffer, value, len);
return 0;
}
int main(int argc, const char * argv[]) {
test("Hello World!", 12);
return 0;
}
- Compile:
gcc test.cpp -o test -fno-stack-protector -O1 - Import and decompile.
- Navigate to
testfunction.
Expected behavior
No junk assignment lines, and memcopy is called with 3 arguments
Screenshots

NOPing stack decrement instruction fixes number of arguments passed to memcopy:

Environment (please complete the following information):
- OS: macOS 10.15.2
- Java Version: 12.0.1
- Ghidra Version: 9.1
Additional context Example program above is built on Linux, but clang on macOS produces similar result.
After some poking around, it turns out assigning register value for length argument works in some cases.
For example, setting ESI = 12 at the function start works, even though it is immediately undefined after PUSH EBP:

On the contrary, setting it only for the relevant instructions doesn't seem to have any effect:

Seems like I'm having troubles understanding how register values work. Is this the expected behavior?
Also, anything more complex than just SUB RSP,RAX doesn't seem to work at all, e.g.
MOV RDI,RSP
SUB RDI,RAX
MOV RSP,RDI
This also seems to influence Rust decompiling, where a "and rsp, X" is used to align the stack. Patch out the and rsp, X gives the correct result. I will do more debug and source reading to see why this happens..
Related to #6002, which seems to report the same error, though the function arguments are correct in the example in issue #6002.