Skip to content

fix(sdk): decode FffGrepMatch and FffScore with the real C layout in fff-node and fff-bun - #891

Merged
dmtrKovalenko merged 1 commit into
mainfrom
fix/sdk-struct-layout-888
Sep 27, 2026
Merged

dmtrKovalenko merged 1 commit into
mainfrom
fix/sdk-struct-layout-888

Conversation

@dmtrKovalenko

@dmtrKovalenko dmtrKovalenko commented Sep 27, 2026 •

Copy link
Copy Markdown
Owner

Fixes #888.

Both SDKs read FffGrepMatch/FffScore by hand-declared layout, and both drifted from the #[repr(C)] structs in crates/fff-c/src/ffi_types.rs. Rust never writes struct padding, so the misread fields came back as whatever the allocator left there — dirty on glibc most of the time, zero on macOS, so it only showed on Linux.

  • fff-node grep: fuzzy_score declared DataType.U32 for a C u16, shifting has_fuzzy_score/is_binary/is_definition 2 bytes into padding. Plain-text hits came back isBinary: true; consumers filtering on it silently dropped results.
  • fff-node score: path_alignment_bonus (in the C struct since feat: Correct bonuses for actual path prefix #372) missing from the decoder, so exactMatch was read from its low byte — false on every exact_filename match.
  • fff-bun score: same field missing from the offset table; SC_EXACT = 32 pointed at path_alignment_bonus.
FffGrepMatch tail          C offset    node read before     node read after
fuzzy_score      u16       128         128..131 (U32)       128..129 (I16 & 0xffff)
has_fuzzy_score  bool      130         132 (=is_definition) 130
is_binary        bool      131         133 (padding)        131
is_definition    bool      132         134 (padding)        132

FffScore                   C offset    bun read before      bun read after
path_alignment_bonus i32   32          —                    32
exact_match          bool  36          32 (wrong field)     36
// fff-node/src/ffi.ts — ffi-rs has no U16, so read I16 and mask
fuzzy_score: DataType.I16,
...
match.fuzzyScore = raw.fuzzy_score & 0xffff;
  • Score.pathAlignmentBonus is now exposed in packages/shared/fff-api.ts for both SDKs.
  • Added fff_score_get_* accessors to fff-c (FffScore was the only exported struct without them); header regenerated.
  • Regression tests in both suites assert exactMatch === true on exact filename hits, no isBinary/isDefinition/fuzzyScore on plain-text grep, and u16-range fuzzyScore in fuzzy mode — each fails against main.

Decoding stays a single struct read per element; no latency change.

Summary by CodeRabbit

  • New Features

    • Search results now expose a path-alignment bonus alongside other score details, including match type and exact-match status.
    • C integrations can retrieve total and component scores, match status, and match type.
  • Bug Fixes

    • Fuzzy grep scores are now reported within the correct unsigned 16-bit range.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your trial has ended. Reactivate Greptile to resume code reviews.

@coderabbitai

coderabbitai Bot commented Sep 27, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: 283d95bc-6dc4-4832-a650-ee900ee2a67e

📥 Commits

Reviewing files that changed from the base of the PR and between 282ffec and 294ae42.

📒 Files selected for processing (9)
  • crates/fff-c/include/fff.h
  • crates/fff-c/src/accessors.rs
  • packages/fff-bun/src/fff-api.ts
  • packages/fff-bun/src/ffi.ts
  • packages/fff-bun/test/index.test.ts
  • packages/fff-node/src/fff-api.ts
  • packages/fff-node/src/ffi.ts
  • packages/fff-node/test/e2e.mjs
  • packages/shared/fff-api.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

The change adds C accessors for FffScore, exposes pathAlignmentBonus in the Bun and Node score APIs, and updates their FFI decoding. The Node grep decoder now reads the fuzzy score as a 16-bit value and masks it before returning it.

Changes

Score and grep FFI

Layer / File(s) Summary
C score accessors
crates/fff-c/include/fff.h, crates/fff-c/src/accessors.rs
The C API adds getters for all FffScore fields. Null pointers return zero, false, or null, depending on the getter. The match-type string is borrowed.
SDK score mapping
packages/shared/fff-api.ts, packages/fff-bun/src/fff-api.ts, packages/fff-node/src/fff-api.ts, packages/fff-bun/src/ffi.ts, packages/fff-node/src/ffi.ts, packages/fff-bun/test/index.test.ts, packages/fff-node/test/e2e.mjs
The score APIs add pathAlignmentBonus. Bun and Node FFI mappings read that field. Exact-filename tests check the match type, exact-match flag, and numeric path-alignment bonus.
Node grep-match decoding
packages/fff-node/src/ffi.ts, packages/fff-node/test/e2e.mjs
The decoder reads fuzzy_score as a signed 16-bit value and masks it to 16 bits. Tests check plain-mode flags and fuzzy scores in the unsigned 16-bit range.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix · Severity of issue fixed: Medium

Suggested reviewers: gustav-fff

Merge Risk: ⚪ Minimal · up to 294ae

The supplied evidence identifies no remaining issue that should delay merging.

Security Architecture Review

Security architecture risk: 🔵 Low · up to 294ae

The changed interfaces expose score data already present in native search results. The SDK changes align decoding with the native layout, and no new security boundary or sensitive-data path was identified. Downstream compatibility and runtime behavior remain partly unverified.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The effective changed exposure is score and grep metadata returned through existing native-result and SDK paths, plus getters available to C callers already holding a score pointer. External C consumers are not enumerated.

Trust Boundaries and Controls

  • inferred — The getter additions do not provide a new way to acquire a native result or change its cleanup authority; no authentication or authorization control change is evidenced in the changed decoding paths.

Resilience and Maintainability Implications

  • inferred — Matching native field widths and offsets matters to consumers that act on isBinary, fuzzyScore, or exactMatch; the added assertions cover representative decoding regressions, but not all platforms or external consumers.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: correcting FffGrepMatch and FffScore decoding to match the real C layout in both SDKs.
Linked Issues check ✅ Passed The PR satisfies the coding objectives in #888. packages/fff-node/src/ffi.ts reads fuzzy_score as I16, masks it to the unsigned 16-bit range, and keeps the following flags at their C-layout posi…
Out of Scope Changes check ✅ Passed The changes stay connected to #888. The Score API fields expose the corrected C-layout value, and the fff-c score accessors and header declarations provide matching public access to the corrected …
Docstring Coverage ✅ Passed Docstring coverage is 86.67% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 15 functions across 9 files.
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@dmtrKovalenko
dmtrKovalenko merged commit 89c1927 into main Sep 27, 2026
57 of 58 checks passed
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.

[Bug]: fff-node grep matches read is_binary / has_fuzzy_score / is_definition from struct padding (u16 fuzzy_score decoded as U32)

1 participant