Fuzzing Crash Report
Analysis
Crash Location: fuzz/fuzz_targets/file_io.rs:100:__libfuzzer_sys_run
Error Message:
assertion `left == right` failed: Length was not preserved expected 1 actual 0.
left: 1
right: 0
Stack Trace
stack backtrace:
0: __rustc::rust_begin_unwind
at /rustc/db3e99bbab28c6ca778b13222becdea54533d908/library/std/src/panicking.rs:689:5
1: core::panicking::panic_fmt
at /rustc/db3e99bbab28c6ca778b13222becdea54533d908/library/core/src/panicking.rs:80:14
2: core::panicking::assert_failed_inner
3: core::panicking::assert_failed::<usize, usize>
at /rustc/db3e99bbab28c6ca778b13222becdea54533d908/library/core/src/panicking.rs:394:5
4: __libfuzzer_sys_run
at ./fuzz/fuzz_targets/file_io.rs:100:5
5: rust_fuzzer_test_input
at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libfuzzer-sys-0.4.12/src/lib.rs:363:60
6: {closure#0}
at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libfuzzer-sys-0.4.12/src/lib.rs:62:9
7: do_call<libfuzzer_sys::test_input_wrap::{closure_env#0}, i32>
at /rustc/db3e99bbab28c6ca778b13222becdea54533d908/library/std/src/panicking.rs:581:40
8: __rust_try
9: catch_unwind<i32, libfuzzer_sys::test_input_wrap::{closure_env#0}>
at /rustc/db3e99bbab28c6ca778b13222becdea54533d908/library/std/src/panicking.rs:544:19
10: catch_unwind<libfuzzer_sys::test_input_wrap::{closure_env#0}, i32>
at /rustc/db3e99bbab28c6ca778b13222becdea54533d908/library/std/src/panic.rs:359:14
11: test_input_wrap
at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libfuzzer-sys-0.4.12/src/lib.rs:60:22
12: _ZN6fuzzer6Fuzzer15ExecuteCallbackEPKhm
at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libfuzzer-sys-0.4.12/libfuzzer/FuzzerLoop.cpp:619:13
13: _ZN6fuzzer10RunOneTestEPNS_6FuzzerEPKcm
at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libfuzzer-sys-0.4.12/libfuzzer/FuzzerDriver.cpp:335:6
14: _ZN6fuzzer12FuzzerDriverEPiPPPcPFiPKhmE
at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libfuzzer-sys-0.4.12/libfuzzer/FuzzerDriver.cpp:871:9
15: main
at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libfuzzer-sys-0.4.12/libfuzzer/FuzzerMain.cpp:20:10
16: <unknown>
17: __libc_start_main
18: _start
Root Cause Analysis
The crash is an assertion failure in the file_io fuzz target (fuzz/fuzz_targets/file_io.rs:100) where a round-trip through the Vortex file writer and reader produces 0 rows instead of the expected 1 row. The fuzzer writes an array to a Vortex file, then reads it back with the same filter and projection expressions, but the scan returns an empty result when in-memory evaluation of the same filter produces one matching row. This strongly suggests a bug in the file reader's filter pushdown or row-group/page-level statistics pruning, where metadata (e.g., zone maps or min/max stats) incorrectly eliminates a chunk that actually contains a matching row, or an off-by-one in row selection logic causes the matching row to be skipped. The fix should investigate the LayoutReader scan path and its pruning logic to find where a valid row is being incorrectly excluded during predicate pushdown.
Summary
Reproduce
cargo +nightly fuzz run -D --sanitizer=none file_io ./fuzz/artifacts/file_io/crash-3f5ef31230b5396e90b652c4114d68da41995906 -- -rss_limit_mb=0
Reproduction Steps
-
Download the crash artifact: https://github.com/vortex-data/vortex/actions/runs/26655876459/artifacts/7304112881
-
Assuming you download the zipfile to ~/Downloads, and your working directory is the repository root:
# Create the artifacts directory if you haven't already.
mkdir -p ./fuzz/artifacts
# Move the zipfile.
mv ~/Downloads/file_io-crash-artifacts.zip ./fuzz/artifacts/
# Unzip the zipfile.
unzip ./fuzz/artifacts/file_io-crash-artifacts.zip -d ./fuzz/artifacts/
# You can remove the zipfile now if you want to.
rm ./fuzz/artifacts/file_io-crash-artifacts.zip
- Reproduce the crash:
cargo +nightly fuzz run -D --sanitizer=none file_io ./fuzz/artifacts/file_io/crash-3f5ef31230b5396e90b652c4114d68da41995906 -- -rss_limit_mb=0
If you want a backtrace:
RUST_BACKTRACE=1 cargo +nightly fuzz run -D --sanitizer=none file_io ./fuzz/artifacts/file_io/crash-3f5ef31230b5396e90b652c4114d68da41995906 -- -rss_limit_mb=0
RUST_BACKTRACE=full cargo +nightly fuzz run -D --sanitizer=none file_io ./fuzz/artifacts/file_io/crash-3f5ef31230b5396e90b652c4114d68da41995906 -- -rss_limit_mb=0
Single command to get a backtrace
mkdir -p ./fuzz/artifacts
mv ~/Downloads/file_io-crash-artifacts.zip ./fuzz/artifacts/
unzip ./fuzz/artifacts/file_io-crash-artifacts.zip -d ./fuzz/artifacts/
rm ./fuzz/artifacts/file_io-crash-artifacts.zip
RUST_BACKTRACE=1 cargo +nightly fuzz run -D --sanitizer=none file_io ./fuzz/artifacts/file_io/crash-3f5ef31230b5396e90b652c4114d68da41995906 -- -rss_limit_mb=0
Auto-created by fuzzing workflow
Fuzzing Crash Report
Analysis
Crash Location:
fuzz/fuzz_targets/file_io.rs:100:__libfuzzer_sys_runError Message:
Stack Trace
Root Cause Analysis
The crash is an assertion failure in the file_io fuzz target (fuzz/fuzz_targets/file_io.rs:100) where a round-trip through the Vortex file writer and reader produces 0 rows instead of the expected 1 row. The fuzzer writes an array to a Vortex file, then reads it back with the same filter and projection expressions, but the scan returns an empty result when in-memory evaluation of the same filter produces one matching row. This strongly suggests a bug in the file reader's filter pushdown or row-group/page-level statistics pruning, where metadata (e.g., zone maps or min/max stats) incorrectly eliminates a chunk that actually contains a matching row, or an off-by-one in row selection logic causes the matching row to be skipped. The fix should investigate the LayoutReader scan path and its pruning logic to find where a valid row is being incorrectly excluded during predicate pushdown.
Summary
file_iocrash-3f5ef31230b5396e90b652c4114d68da41995906Reproduce
Reproduction Steps
Download the crash artifact: https://github.com/vortex-data/vortex/actions/runs/26655876459/artifacts/7304112881
Assuming you download the zipfile to
~/Downloads, and your working directory is the repository root:If you want a backtrace:
Single command to get a backtrace
mkdir -p ./fuzz/artifacts mv ~/Downloads/file_io-crash-artifacts.zip ./fuzz/artifacts/ unzip ./fuzz/artifacts/file_io-crash-artifacts.zip -d ./fuzz/artifacts/ rm ./fuzz/artifacts/file_io-crash-artifacts.zip RUST_BACKTRACE=1 cargo +nightly fuzz run -D --sanitizer=none file_io ./fuzz/artifacts/file_io/crash-3f5ef31230b5396e90b652c4114d68da41995906 -- -rss_limit_mb=0Auto-created by fuzzing workflow