Skip to content

fix: TypeArchive.AddTypes passed the wrong struct to BNAddTypeArchiveTypes#38

Merged
tinysec merged 1 commit into
masterfrom
fix/typearchive-addtypes-wrong-struct
Jul 8, 2026
Merged

fix: TypeArchive.AddTypes passed the wrong struct to BNAddTypeArchiveTypes#38
tinysec merged 1 commit into
masterfrom
fix/typearchive-addtypes-wrong-struct

Conversation

@tinysec

@tinysec tinysec commented Jul 8, 2026

Copy link
Copy Markdown
Owner

Problem

TypeArchive.AddTypes marshaled a BNQualifiedNameTypeAndId struct (40 bytes: name, id, type) and passed it to BNAddTypeArchiveTypes, whose contract is BNQualifiedNameAndType (32 bytes: name, type).

The 8-byte layout mismatch made core read the id pointer at offset 24 as the type handle — so a single-element add dereferenced the id string as a BNType* (garbage/crash), and multi-element arrays were fully mis-strided. No type was ever actually added.

core stride (BNQualifiedNameAndType = 32B):  [name 24B][type 8B]
C#    stride (BNQualifiedNameTypeAndId = 40B): [name 24B][id 8B][type 8B]
                                                ^^^^^^^ core reads this as type

The C# P/Invoke comment even said BNQualifiedNameAndType* types — the wrapper just ignored it.

Fix

Match Python TypeArchive.add_type/add_types (typearchive.py:225/222): callers supply only name and definition; the core assigns the id.

  • AddTypes(QualifiedNameAndType[]) — builds the correct 32-byte struct.
  • AddType(QualifiedName, Type) — convenience (Python add_type).

The id-bearing QualifiedNameTypeAndId struct stays — it is the correct model for the type-reading (BNGetTypeArchiveTypes) and analysis-definition (BNDefineAnalysisTypes) APIs, which legitimately carry ids.

E2E

sharp-binaryninja-tests harness: TypeArchiveAddTypesMarshalingTests — create archive, AddType, assert listable via GetTypeNames; AddTypes second, assert both persist. (Fails on the old 40-byte struct; passes on the fix.)

Verified

  • dotnet build -c Release — 0 warnings, 0 errors.
  • Harness test green.

…Types

AddTypes marshaled a BNQualifiedNameTypeAndId (40 bytes: name, id, type) and passed it
to BNAddTypeArchiveTypes, whose contract is BNQualifiedNameAndType (32 bytes: name,
type). The 8-byte layout mismatch made core read the id pointer at offset 24 as the
type handle, so no type was ever actually added (and multi-element arrays were fully
mis-strided).

Match Python TypeArchive.add_type/add_types (typearchive.py:225/222): callers supply
only name and definition; the core assigns the id. AddTypes now takes
QualifiedNameAndType[] and adds an AddType(name, type) convenience. The id-bearing
QualifiedNameTypeAndId struct stays -- it is the correct model for the type-reading
(BNGetTypeArchiveTypes) and analysis-definition (BNDefineAnalysisTypes) APIs.

E2E: harness TypeArchiveAddTypesMarshalingTests (create archive, AddType, assert
listable; AddTypes second, assert both persist).
@tinysec tinysec merged commit 634af83 into master Jul 8, 2026
1 check passed
@tinysec tinysec deleted the fix/typearchive-addtypes-wrong-struct branch July 8, 2026 17:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant