Fuzzing Crash Report
Analysis
Crash Location: fuzz/fuzz_targets/file_io.rs:95:__libfuzzer_sys_run
Error Message:
assertion `left == right` failed: Length was not preserved expected 73 actual 74.
left: 73
right: 74
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:95: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: _ZN6fuzzer6Fuzzer6RunOneEPKhmbPNS_9InputInfoEbPb
at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libfuzzer-sys-0.4.12/libfuzzer/FuzzerLoop.cpp:516:7
14: _ZN6fuzzer6Fuzzer25ReadAndExecuteSeedCorporaERSt6vectorINS_9SizedFileESaIS2_EE
at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libfuzzer-sys-0.4.12/libfuzzer/FuzzerLoop.cpp:834:7
15: _ZN6fuzzer6Fuzzer4LoopERSt6vectorINS_9SizedFileESaIS2_EE
at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libfuzzer-sys-0.4.12/libfuzzer/FuzzerLoop.cpp:872:3
16: _ZN6fuzzer12FuzzerDriverEPiPPPcPFiPKhmE
at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libfuzzer-sys-0.4.12/libfuzzer/FuzzerDriver.cpp:923:6
17: main
at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libfuzzer-sys-0.4.12/libfuzzer/FuzzerMain.cpp:20:10
18: <unknown>
19: __libc_start_main
20: _start
Root Cause Analysis
The crash is an assertion failure in the file_io fuzz target (file_io.rs:95) where the array length after a write-read roundtrip does not match the original: expected 73 rows but got 74. The input is a ChunkedArray of Structs with nested ChunkedArray fields, nullable F32 columns, and a filter expression (gte on an F32 field) combined with a projection selecting a single field — this combination likely causes an off-by-one error in row count computation during filtered reads, where the filter predicate boundary interacts incorrectly with chunk boundaries in the nested struct layout. The fix should investigate how filtered scan results are accumulated across chunks in the layout reader, particularly when a filter pushdown crosses chunk boundaries in a chunked/nested struct array, as the extra row suggests an inclusive-vs-exclusive boundary bug in the chunk-level row range computation.
Summary
Reproduction
-
Download the crash artifact:
-
Reproduce locally:
cargo +nightly fuzz run -D --sanitizer=none file_io /path/to/crash_file -- -rss_limit_mb=0
- Get a backtrace:
RUST_BACKTRACE=1 cargo +nightly fuzz run -D --sanitizer=none file_io /path/to/crash_file -- -rss_limit_mb=0
RUST_BACKTRACE=full cargo +nightly fuzz run -D --sanitizer=none file_io /path/to/crash_file -- -rss_limit_mb=0
Workflow Example
Assuming you download the zipfile to ~/Downloads, and your working directory is the repository
root, you can follow these steps:
# 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
You can now reproduce with:
cargo +nightly fuzz run -D --sanitizer=none file_io ./fuzz/artifacts/file_io/crash-176043a5dfdc3857e16c8a9852f0aae79cd43f77 -- -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-176043a5dfdc3857e16c8a9852f0aae79cd43f77 -- -rss_limit_mb=0
RUST_BACKTRACE=full cargo +nightly fuzz run -D --sanitizer=none file_io ./fuzz/artifacts/file_io/crash-176043a5dfdc3857e16c8a9852f0aae79cd43f77 -- -rss_limit_mb=0
Auto-created by fuzzing workflow
Fuzzing Crash Report
Analysis
Crash Location:
fuzz/fuzz_targets/file_io.rs:95:__libfuzzer_sys_runError Message:
Stack Trace
Root Cause Analysis
The crash is an assertion failure in the file_io fuzz target (file_io.rs:95) where the array length after a write-read roundtrip does not match the original: expected 73 rows but got 74. The input is a ChunkedArray of Structs with nested ChunkedArray fields, nullable F32 columns, and a filter expression (gte on an F32 field) combined with a projection selecting a single field — this combination likely causes an off-by-one error in row count computation during filtered reads, where the filter predicate boundary interacts incorrectly with chunk boundaries in the nested struct layout. The fix should investigate how filtered scan results are accumulated across chunks in the layout reader, particularly when a filter pushdown crosses chunk boundaries in a chunked/nested struct array, as the extra row suggests an inclusive-vs-exclusive boundary bug in the chunk-level row range computation.
Summary
file_iocrash-176043a5dfdc3857e16c8a9852f0aae79cd43f77Reproduction
Download the crash artifact:
unzip)/path/to/file_io/crash-176043a5dfdc3857e16c8a9852f0aae79cd43f77./fuzz/artifactsdirectory that will be git-ignored in thevortexrepo./fuzz/artifacts/file_io/crash-176043a5dfdc3857e16c8a9852f0aae79cd43f77Reproduce locally:
Workflow Example
Assuming you download the zipfile to
~/Downloads, and your working directory is the repositoryroot, you can follow these steps:
You can now reproduce with:
If you want a backtrace:
Auto-created by fuzzing workflow