Skip to content

fix(nvim): refuse fs-root/home index at Lua level before FFI (#745) - #748

Merged
dmtrKovalenko merged 2 commits into
mainfrom
triage-bot/issue-745
Aug 7, 2026
Merged

fix(nvim): refuse fs-root/home index at Lua level before FFI (#745)#748
dmtrKovalenko merged 2 commits into
mainfrom
triage-bot/issue-745

Conversation

@gustav-fff

Copy link
Copy Markdown
Collaborator

Closes #745

Root cause

Opening nvim at / with lazy=false kills the entire neovim process on the CI-cross-compiled aarch64 .so. The Rust side is supposed to return Error::FilesystemRoot cleanly (crates/fff-core/src/file_picker.rs:862), and a native cargo build --release does exactly that. But the published aarch64 binary SIGSEGVs at the init_file_picker FFI call instead of returning the error — as the reporter confirmed (exit=139, core dump, corrupt stack; native build exits 0).

A SIGSEGV is a hardware signal. The pcall around init_file_picker (lua/fff/core.lua) cannot catch it, so it propagates and takes neovim down. The SIGSEGV banner in the crash buffer comes from fff's own signal handler (crates/fff-core/src/log.rs:54).

The underlying aarch64 codegen/segfault is a separate issue for @dmtrKovalenko. This PR is the Lua-level workaround requested in #745 (comment).

Fix

Mirror the Rust root/home refusal in Lua and bail before crossing the FFI boundary, so the crashing path is never reached:

  • ensure_initialized refuses when base_path is a filesystem root (/, C:) or $HOME with the matching scan flag disabled, notifies at WARN, and returns without calling into Rust.
  • change_indexing_directory gets the same guard for the :cd /-after-init case.
  • Honors existing enable_fs_root_scanning / enable_home_dir_scanning overrides — no new config, no behavior change when scanning is allowed.

~40 LOC, lua/fff/core.lua only.

Steps to reproduce

On pre-fix main, published aarch64 build (or any build where the FFI segfaults):

$ cd / && nvim --headless -c "lua require('fff.core').ensure_initialized()" -c "qa!"; echo "exit=$?"

=== CRASH SIGSEGV (fff) ===
=== CRASH END SIGSEGV ===
Segmentation fault (core dumped)
exit=139

Expected: clean refusal, neovim survives. Actual: SIGSEGV, exit 139, core dump.

How verified

Logic of the guard validated in isolation under headless nvim (the module itself needs the compiled backend to load):

$ nvim --headless -l /tmp/test_refusal.lua
root / refused                           got=Refusing to index filesystem root. ...
root / allowed                           got=nil
home refused                             got=Refusing to index home directory. ...
home allowed (default)                   got=nil
normal dir ok                            got=nil
root // refused                          got=Refusing to index filesystem root. ...
ALL PASS

stylua --check lua/fff/core.lua passes.

Post-fix, ensure_initialized at / returns without touching the FFI, so neovim no longer crashes regardless of the aarch64 codegen bug.

Automated triage via Gustav. Honk-Honk 🪿

Opening nvim at `/` with lazy=false crashed the whole neovim process on
CI-cross-compiled aarch64 .so binaries: the init_file_picker FFI call
SIGSEGVs instead of returning Error::FilesystemRoot cleanly. A SIGSEGV
is a hardware signal that the pcall around init_file_picker cannot catch.

Mirror the Rust refusal (file_picker.rs:862) in Lua and bail before
crossing the FFI boundary, so the crashing path is never reached. Same
guard added to change_indexing_directory for the :cd-into-root case.
Honors enable_fs_root_scanning / enable_home_dir_scanning overrides.
@dmtrKovalenko

Copy link
Copy Markdown
Owner

@gustav-fff remove all the comments you wrote (they are slop) and leave the only one

-- Some folks are complaining that neovim instance is closing if ffi returns error on startup (via lazy=false)
-- I can't repro so just precheck on lua side to prevent crashing neovim instance

@gustav-fff

Copy link
Copy Markdown
Collaborator Author

[triage-bot] DIRECTED: Done. 96f8814 strips all comments from the guard in lua/fff/core.lua, keeping only the requested two-liner above the fs_scanning_refusal call in ensure_initialized. Also dropped the doc-comment on the function and the forward-declaration note. Pushed to triage-bot/issue-745. stylua clean.

Honk-Honk 🪿

@dmtrKovalenko
dmtrKovalenko merged commit 4afad82 into main Aug 7, 2026
43 of 50 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.

Segfault instead of a clean error when base_path is the filesystem root (/)

2 participants