Vector35 / Vector35/binaryninja-api
HLIL infers wrong type when dereferencing a struct containing a single pointer type
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 1.3k
- Forks
- 298
- Avg merge
- 5d 5h
- Merged PRs (30d)
- 19
Description
Version and Platform (required):
- Binary Ninja Version: 2.5.3165-dev
- OS: macos
- OS Version: 10.15.7
Bug Description:
Struct types with a single pointer type member produce incorrect HLIL when dereferencing the member. For example, given:
struct foo {
struct bar *bar;
};
Dereferences of the form foo->bar are automatically typed as struct foo in Binary Ninja instead of struct bar *.
This only happens when the containing struct only contains a single pointer member. If we define foo as:
struct foo {
struct bar *bar;
int x;
};
this no longer happens, and foo->bar is correctly typed as struct bar *.
My (rudamentary) guess is that Binary Ninja is treating foo as an alias for struct bar * and "upgrades" struct bar * into struct foo when it shouldn't.
Steps To Reproduce:
Compile this program and open in Binary Ninja:
struct bar {
int a;
int b;
};
struct foo {
struct bar *bar;
};
void fn(struct foo *f) {
f->bar->a += 1;
f->bar->b -= 1;
}
int main() {
struct bar b = {
.a=3,
.b=4
};
struct foo f = {
.bar=&b
};
struct foo *f_ref = &f;
fn(f_ref);
}
Define the types foo and bar in the types panel and then annotate the function signature of fn to have one argument of type foo *.
Expected Behavior:
HLIL should look like this:

Wrong Behavior:
Current versions produce HLIL that looks like this:

(note that arg1->bar is assigned type foo)
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the supplied C reproduction and open it in Binary Ninja 2.5.3165-dev on macOS. Define foo and bar in the Types panel, annotate fn with a foo * argument, and inspect the HLIL for f->bar->a and f->bar->b; done means the member is typed as struct bar * rather than struct foo.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- reverse-engineering
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100