Skip to content

Fuzzing Crash: VortexError in array_ops #8145

Description

@github-actions

Fuzzing Crash Report

Analysis

Crash Location: fuzz/fuzz_targets/array_ops.rs:33:assert_min_max_eq

Error Message:

Other error: MinMax mismatch: expected Some(MinMaxResult { min: Scalar { dtype: Primitive(U32, NonNullable), value: Some(Primitive(U32(0))) }, max: Scalar { dtype: Primitive(U32, NonNullable), value: Some(Primitive(U32(7631471))) } }) got Some(MinMaxResult { min: Scalar { dtype: Primitive(U32, NonNullable), value: Some(Primitive(U32(0))) }, max: Scalar { dtype: Primitive(U32, NonNullable), value: Some(Primitive(U32(4294967295))) } }) in step 3
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: __libfuzzer_sys_run
             at ./fuzz/fuzz_targets/array_ops.rs:33:19
   4: rust_fuzzer_test_input
             at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libfuzzer-sys-0.4.12/src/lib.rs:363:60
   5: {closure#0}
             at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libfuzzer-sys-0.4.12/src/lib.rs:62:9
   6: do_call<libfuzzer_sys::test_input_wrap::{closure_env#0}, i32>
             at /rustc/db3e99bbab28c6ca778b13222becdea54533d908/library/std/src/panicking.rs:581:40
   7: __rust_try
   8: catch_unwind<i32, libfuzzer_sys::test_input_wrap::{closure_env#0}>
             at /rustc/db3e99bbab28c6ca778b13222becdea54533d908/library/std/src/panicking.rs:544:19
   9: catch_unwind<libfuzzer_sys::test_input_wrap::{closure_env#0}, i32>
             at /rustc/db3e99bbab28c6ca778b13222becdea54533d908/library/std/src/panic.rs:359:14
  10: test_input_wrap
             at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libfuzzer-sys-0.4.12/src/lib.rs:60:22
  11: _ZN6fuzzer6Fuzzer15ExecuteCallbackEPKhm
             at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libfuzzer-sys-0.4.12/libfuzzer/FuzzerLoop.cpp:619:13
  12: _ZN6fuzzer10RunOneTestEPNS_6FuzzerEPKcm
             at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libfuzzer-sys-0.4.12/libfuzzer/FuzzerDriver.cpp:335:6
  13: _ZN6fuzzer12FuzzerDriverEPiPPPcPFiPKhmE
             at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libfuzzer-sys-0.4.12/libfuzzer/FuzzerDriver.cpp:871:9
  14: main
             at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libfuzzer-sys-0.4.12/libfuzzer/FuzzerMain.cpp:20:10
  15: <unknown>
  16: __libc_start_main
  17: _start

Root Cause Analysis

The crash is a MinMax statistics mismatch in the array_ops fuzzer at fuzz/fuzz_targets/array_ops.rs:33, where the min_max computation on a compressed/encoded U32 array returns a max of 4294967295 (u32::MAX) instead of the expected 7631471. This occurs at step 3 of a fuzz action sequence, meaning the array has undergone multiple transformations (e.g., compress, slice, filter) before the MinMax check, and one of those encoding-specific min_max implementations is computing an incorrect maximum. The u32::MAX value strongly suggests either an overflow in an encoding's algebraic min/max computation (such as the sequence encoding's checked_mul/checked_add for last-value calculation) or a fill-value/metadata initialization bug in an encoding like sparse or run-end that causes an uninitialized or default max to leak through. The fix should trace which encoding the array uses at step 3 of this specific crash input and audit that encoding's min_max implementation for overflow handling and edge cases around empty or single-element partitions.

Summary

Reproduce

cargo +nightly fuzz run -D --sanitizer=none array_ops ./fuzz/artifacts/array_ops/crash-e03a12a2d9b9c6f4d54b193f4082b7fd1a3d54ae -- -rss_limit_mb=0
Reproduction Steps
  1. Download the crash artifact: https://github.com/vortex-data/vortex/actions/runs/26610507473/artifacts/7287062727

  2. 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/array_ops-crash-artifacts.zip ./fuzz/artifacts/

# Unzip the zipfile.
unzip ./fuzz/artifacts/array_ops-crash-artifacts.zip -d ./fuzz/artifacts/

# You can remove the zipfile now if you want to.
rm ./fuzz/artifacts/array_ops-crash-artifacts.zip
  1. Reproduce the crash:
cargo +nightly fuzz run -D --sanitizer=none array_ops ./fuzz/artifacts/array_ops/crash-e03a12a2d9b9c6f4d54b193f4082b7fd1a3d54ae -- -rss_limit_mb=0

If you want a backtrace:

RUST_BACKTRACE=1 cargo +nightly fuzz run -D --sanitizer=none array_ops ./fuzz/artifacts/array_ops/crash-e03a12a2d9b9c6f4d54b193f4082b7fd1a3d54ae -- -rss_limit_mb=0
RUST_BACKTRACE=full cargo +nightly fuzz run -D --sanitizer=none array_ops ./fuzz/artifacts/array_ops/crash-e03a12a2d9b9c6f4d54b193f4082b7fd1a3d54ae -- -rss_limit_mb=0
Single command to get a backtrace
mkdir -p ./fuzz/artifacts
mv ~/Downloads/array_ops-crash-artifacts.zip ./fuzz/artifacts/
unzip ./fuzz/artifacts/array_ops-crash-artifacts.zip -d ./fuzz/artifacts/
rm ./fuzz/artifacts/array_ops-crash-artifacts.zip
RUST_BACKTRACE=1 cargo +nightly fuzz run -D --sanitizer=none array_ops ./fuzz/artifacts/array_ops/crash-e03a12a2d9b9c6f4d54b193f4082b7fd1a3d54ae -- -rss_limit_mb=0

Auto-created by fuzzing workflow

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugA bug issuefuzzerIssues detected by the fuzzer

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions