Skip to content

fix: navigation parity — GetFunctionAt explicit-platform + InstructionTextLine address#30

Merged
tinysec merged 1 commit into
masterfrom
fix/navigation-parity-getfunctionat-address
Jul 8, 2026
Merged

fix: navigation parity — GetFunctionAt explicit-platform + InstructionTextLine address#30
tinysec merged 1 commit into
masterfrom
fix/navigation-parity-getfunctionat-address

Conversation

@tinysec

@tinysec tinysec commented Jul 8, 2026

Copy link
Copy Markdown
Owner

Two confirmed deviations from the navigation-layer parity audit (each adversarially verified against the official Python binding; audit was a 20-method fan-out workflow).

1. BinaryView.GetFunctionAt — wrong-platform function (bug)

When the caller passed an explicit platform that has no function at the address, the code still fell through to candidates[0], returning a different platform's Function. Python get_function_at (binaryview.py:5846) is a strict BNGetAnalysisFunction(view, plat, addr) lookup in that branch and returns None.

Fix: gate the candidates[0] fallback on platform == null. Implicit-platform lookups still fall back (matches Python plat=None); an explicit platform with no match returns null.

2. InstructionTextLine — per-instruction address dropped (parity gap)

Python Function.instructions / BinaryView.instructions yield (tokens, addr). The C# InstructionTextLine carried only Tokens; the producer BasicBlock.GetInstructionTextLines computed the running address then discarded it at the yield.

Fix: add an Address property (+ (tokens, address) ctor) to InstructionTextLine and populate it at the single producer site. Function.GetInstructions / BinaryView.GetInstructions / BasicBlock.GetInstructionByIndex all carry the address for free. (Existing token-only ctor retained for non-address callers; defaults Address to 0.)

Audit context

  • 20 navigation methods audited 1:1 against Python; 7 confirmed deviations, 1 refuted (benign), 3 verify-agents rate-limited.
  • This PR fixes the 2 behavior-affecting ones. Remaining confirmed items are minor/design (see follow-ups): DerivedString custom_type/value-shape/location-shape, GetInstructionByIndex negative-index house-style.
  • The 3 rate-limited items re-checked by hand: StructureType.GetMemberByName (null-vs-raise = house-style), GetMediumLevelILInstructions (mirrors the matched LLIL generator), GetHighLevelILInstructions (empirically verified: forcing HLIL via the HighLevelIL property matches Python hlil_functions(); GetHighLevelILIfAvailable() null is the lazy-not-preloaded state, not a crash).

Verification

  • dotnet build -c Release clean.
  • Harness: +2 tests (foreign-platform → null; first line carries entry-block address). 46/46 pass.

…nTextLine address

Two confirmed deviations from the navigation-layer parity audit (each
adversarially verified against the official Python binding):

1. BinaryView.GetFunctionAt returned a WRONG-PLATFORM function. When the
   caller passed an explicit platform that has no function at the address,
   the code still fell through to candidates[0]. Python's get_function_at
   (binaryview.py:5846) is a strict BNGetAnalysisFunction(view, plat, addr)
   lookup in that branch and returns None. Fix: gate the candidates[0]
   fallback on platform == null; an explicit platform with no match returns
   null (the implicit-platform path still falls back, matching Python).

2. InstructionTextLine dropped the per-instruction address. Python's
   Function.instructions / BinaryView.instructions generators yield
   (tokens, addr); the C# InstructionTextLine carried only Tokens, and the
   producer BasicBlock.GetInstructionTextLines computed the running address
   then discarded it at the yield. Fix: add an Address property (and a
   (tokens, address) constructor) to InstructionTextLine and populate it at
   the single producer site; Function.GetInstructions / BinaryView.GetInstructions
   / BasicBlock.GetInstructionByIndex all carry the address for free.
@tinysec tinysec merged commit 6254d82 into master Jul 8, 2026
1 check passed
@tinysec tinysec deleted the fix/navigation-parity-getfunctionat-address branch July 8, 2026 15:22
tinysec added a commit that referenced this pull request Jul 8, 2026
Completes HIGH parity gap #30 (PR #30 added the address half; this
adds the byte-size half). Python's BasicBlock.__getitem__ yields
(tokens, size) per instruction, so the size is as much a part of an
instruction's identity as its address. InstructionTextLine previously
computed the decoded length at the producer and then dropped it, so a
caller could not recover HOW LONG an instruction was -- and a block's
last instruction has no successor, so its size could not even be
derived from consecutive Addresses.

Add InstructionTextLine.ByteSize (default 0 for synthesized token
lists) and a (tokens, address, byteSize) constructor; populate it at
the single producer site (BasicBlock.GetInstructionTextLines), which
feeds Function.GetInstructions / BinaryView.GetInstructions /
BasicBlock.GetInstructionByIndex.
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