Hex-Rays' blog

Igor’s Tip of the Week #155: Splitting stack variables in the decompiler – Hex Rays

Written by Igor Skochinsky | Sep 1, 2023

We’ve covered splitting expressions before, but there may be situations where it can’t be used.

For example, consider following situation:

The decompiler decided that the function returns a 64-bit integer and allocated a 64-bit stack varible for it. For example, the code may be manipulating a register pair commonly used for 64-bit variables (eax:edx) which triggers the heirustics for recovering 64-bit calculations. However, here it seems to be a false positive: we can see separate accesses to the low and high dword of the variable, and the third argument for the IndexFromId call also uses a pointer into the middle of the variable.

One option is to hint to the decompiler that the function returns a 32-bit integer by editing the function’s prototype (use “Set item type” or the Y shotrcut on the first line). 

Often this fixes the decompilation, but not here:

We still have a 64-bt variable on the stack at ebp-10h, so it’s worth inspecting the stack frame. It can be opened by pressing Ctrl-K in disassembly view or double-cliking stack variable in disassembly or pseudocode:

We see that there is a quadword (64-bit) variable at offset -10. it can be converted to 32-bit(dword) by pressing D three times. Another dword can be added in the same manner at offset -C:

After refreshing pseudocode, we can see improved output:

There’s only one small issue: v5 became an array. This happened bcause passing an array or an address of a single integer produces the same code but there was a gap in the stack frame after var_C, so the decompiler decided that it’s actually an array. If you’re certain that it’s a single integer, you have the following options:

  1. Edit the stack frame again and define some variables after var_C so that there is no space for an array.
  2. retype v5 directly from the pseudocode (use Y and enter ‘int’).

Now the pseudocode looks correct and there is only one variable of correct size:

Note that in some cases a variable passed by address may be really an array, or a structure – in case of doubt inspect the called function to confirm how the argument is being used.

See also:

Igor’s tip of the week #65: stack frame view

Igor’s tip of the week #42: Renaming and retyping in the decompiler