Fuzzing Crash Report
Analysis
Crash Location: vortex-array/src/arrays/decimal/compute/between.rs:70:between_unpack
Error Message:
collect should succeed in fuzz test:
invalid upper bound Scalar: decimal32(82246, precision=5, scale=-67), expected I16
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: panic_display<vortex_error::VortexError>
at /rustc/db3e99bbab28c6ca778b13222becdea54533d908/library/core/src/panicking.rs:259:5
3: {closure#1}<alloc::vec::Vec<vortex_array::array::erased::ArrayRef, alloc::alloc::Global>, vortex_error::VortexError>
at ./vortex-error/src/lib.rs:507:9
4: unwrap_or_else<alloc::vec::Vec<vortex_array::array::erased::ArrayRef, alloc::alloc::Global>, vortex_error::VortexError, vortex_error::{impl#11}::vortex_expect::{closure_env#1}<alloc::vec::Vec<vortex_array::array::erased::ArrayRef, alloc::alloc::Global>, vortex_error::VortexError>>
at /rustc/db3e99bbab28c6ca778b13222becdea54533d908/library/core/src/result.rs:1622:23
5: vortex_expect<alloc::vec::Vec<vortex_array::array::erased::ArrayRef, alloc::alloc::Global>, vortex_error::VortexError>
at ./vortex-error/src/lib.rs:347:14
6: __libfuzzer_sys_run
at ./fuzz/fuzz_targets/file_io.rs:92:10
7: rust_fuzzer_test_input
at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libfuzzer-sys-0.4.12/src/lib.rs:363:60
8: {closure#0}
at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libfuzzer-sys-0.4.12/src/lib.rs:62:9
9: do_call<libfuzzer_sys::test_input_wrap::{closure_env#0}, i32>
at /rustc/db3e99bbab28c6ca778b13222becdea54533d908/library/std/src/panicking.rs:581:40
10: __rust_try
11: catch_unwind<i32, libfuzzer_sys::test_input_wrap::{closure_env#0}>
at /rustc/db3e99bbab28c6ca778b13222becdea54533d908/library/std/src/panicking.rs:544:19
12: catch_unwind<libfuzzer_sys::test_input_wrap::{closure_env#0}, i32>
at /rustc/db3e99bbab28c6ca778b13222becdea54533d908/library/std/src/panic.rs:359:14
13: test_input_wrap
at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libfuzzer-sys-0.4.12/src/lib.rs:60:22
14: _ZN6fuzzer6Fuzzer15ExecuteCallbackEPKhm
at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libfuzzer-sys-0.4.12/libfuzzer/FuzzerLoop.cpp:619:13
15: _ZN6fuzzer10RunOneTestEPNS_6FuzzerEPKcm
at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libfuzzer-sys-0.4.12/libfuzzer/FuzzerDriver.cpp:335:6
16: _ZN6fuzzer12FuzzerDriverEPiPPPcPFiPKhmE
at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libfuzzer-sys-0.4.12/libfuzzer/FuzzerDriver.cpp:871:9
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 occurs in between_unpack at vortex-array/src/arrays/decimal/compute/between.rs:70, where casting the upper bound scalar (decimal32 with scale=-67) to the expected native decimal type (I16/decimal16) fails. The root cause is a mismatch between the array's decimal storage type and the bound scalars' decimal storage type: the match_each_decimal_value_type! macro dispatches based on the array's values_type (decimal16/I16), but the upper bound scalar is a decimal32 (backed by I32), so the cast returns None and triggers the bail. The comment on line 31 notes that precision and scale are checked upstream, but the decimal width (decimal16 vs decimal32) is not validated, allowing the fuzzer to construct inputs where the array and bounds have incompatible decimal representations. The fix should either validate that the bound scalars' decimal type matches the array's decimal type before dispatching, or rescale/cast the bounds to the array's decimal type within between_unpack.
Summary
Reproduce
cargo +nightly fuzz run -D --sanitizer=none file_io ./fuzz/artifacts/file_io/crash-461fde5a01c8d25969854604424a7ddefd23cbd2 -- -rss_limit_mb=0
Reproduction Steps
-
Download the crash artifact: https://github.com/vortex-data/vortex/actions/runs/25934561676/artifacts/7027711321
-
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-461fde5a01c8d25969854604424a7ddefd23cbd2 -- -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-461fde5a01c8d25969854604424a7ddefd23cbd2 -- -rss_limit_mb=0
RUST_BACKTRACE=full cargo +nightly fuzz run -D --sanitizer=none file_io ./fuzz/artifacts/file_io/crash-461fde5a01c8d25969854604424a7ddefd23cbd2 -- -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-461fde5a01c8d25969854604424a7ddefd23cbd2 -- -rss_limit_mb=0
Auto-created by fuzzing workflow
Fuzzing Crash Report
Analysis
Crash Location:
vortex-array/src/arrays/decimal/compute/between.rs:70:between_unpackError Message:
Stack Trace
Root Cause Analysis
The crash occurs in between_unpack at vortex-array/src/arrays/decimal/compute/between.rs:70, where casting the upper bound scalar (decimal32 with scale=-67) to the expected native decimal type (I16/decimal16) fails. The root cause is a mismatch between the array's decimal storage type and the bound scalars' decimal storage type: the match_each_decimal_value_type! macro dispatches based on the array's values_type (decimal16/I16), but the upper bound scalar is a decimal32 (backed by I32), so the cast returns None and triggers the bail. The comment on line 31 notes that precision and scale are checked upstream, but the decimal width (decimal16 vs decimal32) is not validated, allowing the fuzzer to construct inputs where the array and bounds have incompatible decimal representations. The fix should either validate that the bound scalars' decimal type matches the array's decimal type before dispatching, or rescale/cast the bounds to the array's decimal type within between_unpack.
Summary
file_iocrash-461fde5a01c8d25969854604424a7ddefd23cbd2Reproduce
Reproduction Steps
Download the crash artifact: https://github.com/vortex-data/vortex/actions/runs/25934561676/artifacts/7027711321
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-461fde5a01c8d25969854604424a7ddefd23cbd2 -- -rss_limit_mb=0Auto-created by fuzzing workflow