Skip to content

Fuzzing Crash: VortexError in array_ops #10764

Open

Description

@github-actions

Fuzzing Crash Report

Analysis

Crash Location: vortex-array/src/optimizer/rules.rs:202:evaluate

Error Message:

slice operation should succeed in fuzz test:
  Other error: Reduced array dtype mismatch from ArrayParentReduceRuleAdapter { parent: "vortex_array::arrays::slice::vtable::Slice", rule: SliceReduceAdaptor(Dict) }
From:
vortex.slice
To:
vortex.dict
  left: bool
 right: bool?
Stack Trace
stack backtrace:
   0: __rustc::rust_begin_unwind
             at /rustc/a36d05efab632d1ddf902b6a5c33b6d5d3b64131/library/std/src/panicking.rs:676:5
   1: core::panicking::panic_fmt
             at /rustc/a36d05efab632d1ddf902b6a5c33b6d5d3b64131/library/core/src/panicking.rs:80:14
   2: panic_display<vortex_error::VortexError>
             at /rustc/a36d05efab632d1ddf902b6a5c33b6d5d3b64131/library/core/src/panicking.rs:259:5
   3: result_expect_failed<vortex_error::VortexError>
             at ./vortex-error/src/lib.rs:716:9
   4: run_fuzz_action
   5: __libfuzzer_sys_run
             at ./fuzz/fuzz_targets/array_ops.rs:30:11
   6: rust_fuzzer_test_input
             at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libfuzzer-sys-0.4.13/src/lib.rs:363:60
   7: {closure#0}
             at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libfuzzer-sys-0.4.13/src/lib.rs:62:9
   8: do_call<libfuzzer_sys::test_input_wrap::{closure_env#0}, i32>
             at /rustc/a36d05efab632d1ddf902b6a5c33b6d5d3b64131/library/std/src/panicking.rs:573:43
   9: __rust_try
  10: catch_unwind<i32, libfuzzer_sys::test_input_wrap::{closure_env#0}>
             at /rustc/a36d05efab632d1ddf902b6a5c33b6d5d3b64131/library/std/src/panicking.rs:541:19
  11: catch_unwind<libfuzzer_sys::test_input_wrap::{closure_env#0}, i32>
             at /rustc/a36d05efab632d1ddf902b6a5c33b6d5d3b64131/library/std/src/panic.rs:359:14
  12: test_input_wrap
             at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libfuzzer-sys-0.4.13/src/lib.rs:60:22
  13: _ZN6fuzzer6Fuzzer15ExecuteCallbackEPKhm
             at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libfuzzer-sys-0.4.13/libfuzzer/FuzzerLoop.cpp:619:15
  14: _ZN6fuzzer10RunOneTestEPNS_6FuzzerEPKcm
             at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libfuzzer-sys-0.4.13/libfuzzer/FuzzerDriver.cpp:335:21
  15: _ZN6fuzzer12FuzzerDriverEPiPPPcPFiPKhmE
             at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libfuzzer-sys-0.4.13/libfuzzer/FuzzerDriver.cpp:871:19
  16: main
             at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libfuzzer-sys-0.4.13/libfuzzer/FuzzerMain.cpp:20:30
  17: __libc_start_call_main
             at ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16
  18: __libc_start_main_impl
             at ./csu/../csu/libc-start.c:360:3
  19: _start

Root Cause Analysis

The array_ops fuzz target panicked because a slice operation returned a VortexError (Other). The error comes from the debug-only dtype check in the optimizer's parent-reduce loop at vortex-array/src/optimizer/rules.rs:202. The rule SliceReduceAdaptor(Dict) rewrote a Slice over a DictArray into a new DictArray whose dtype is non-nullable bool, while the Slice it replaced had dtype nullable bool (bool?). The optimizer requires a reduction to keep the parent's dtype, so it rejects the rewrite.

The likely cause is slice_constant_code in vortex-array/src/arrays/dict/compute/slice.rs. A DictArray's dtype is the values dtype unioned with the codes' nullability (DictArray::new / new_unchecked in vortex-array/src/arrays/dict/array.rs). Here the values are non-nullable bool and the codes are nullable integers, so the Dict is bool?. Dict::slice takes the constant-code shortcut either when the codes are already a ConstantArray or when the sliced codes reduce to one. When the constant code is a valid (non-null) value, the shortcut builds DictArray::new(ConstantArray::new(0u8, len), values.slice(code..code + 1)). The literal 0u8 gives non-nullable codes, so the codes' nullability is lost and the result's dtype narrows from bool? to bool. Only the null-code branch keeps the original dtype, because it uses array.dtype() directly.

To fix it, build the replacement codes with the original codes' nullability, for example a ConstantArray of Scalar::primitive(0u8, array.codes().dtype().nullability()). Alternatively, cast the result back to array.dtype(). A regression test like the existing slice_constant_valid_code, but with nullable constant codes over non-nullable values, should reproduce the mismatch.

Summary

Reproduce

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

  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-8472706dcc57130396bc29613138ed1e788ef3e1 -- -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-8472706dcc57130396bc29613138ed1e788ef3e1 -- -rss_limit_mb=0
RUST_BACKTRACE=full cargo +nightly fuzz run -D --sanitizer=none array_ops ./fuzz/artifacts/array_ops/crash-8472706dcc57130396bc29613138ed1e788ef3e1 -- -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-8472706dcc57130396bc29613138ed1e788ef3e1 -- -rss_limit_mb=0

Auto-created by fuzzing workflow

Activity

  1. github-actions commented on Oct 24, 2026

    @github-actions
    ContributorAuthor

    Seen 2 times

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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