Skip to content

Fuzzing Crash: VortexError in array_ops #8145

@github-actions

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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions