Vector35 / Vector35/binaryninja-api

HLIL infers wrong type when dereferencing a struct containing a single pointer type

Open
#2,836 1 comment 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Component: Core Effort: Low Impact: Low
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:
Screen Shot 2022-01-12 at 2 42 32 PM

Wrong Behavior:
Current versions produce HLIL that looks like this:
Screen Shot 2022-01-12 at 2 42 06 PM

(note that arg1->bar is assigned type foo)

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.