Skip to content

Fuzzing Crash: Decimal Sum Overflow in ChunkedArray #5811

Description

@github-actions

Fuzzing Crash Report

Analysis

Crash Location: fuzz/src/array/mod.rs:assert_scalar_eq

Error Message:

Scalar mismatch: expected decimal256(27897708223554751832957193840191214563962497566384571035819434488814200889077, precision=76, scale=75), got null in step 1

Stack Trace:

   3: assert_scalar_eq
             at ./fuzz/src/array/mod.rs:705:13
   4: run_fuzz_action
             at ./fuzz/src/array/mod.rs:587:17
   5: __libfuzzer_sys_run
             at ./fuzz/fuzz_targets/array_ops.rs:14:11
   6: rust_fuzzer_test_input
             at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libfuzzer-sys-0.4.10/src/lib.rs:363:60
   7: {closure#0}
             at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libfuzzer-sys-0.4.10/src/lib.rs:62:9

Root Cause:

The fuzzer discovered a case where summing decimal values in a ChunkedArray results in an i256 overflow. When this happens, the sum implementation correctly returns null (as documented in vortex-array/src/compute/sum.rs:44 and tested in vortex-array/src/arrays/decimal/compute/sum.rs:363-377). However, the fuzzer's expectation logic doesn't account for this overflow behavior, causing a mismatch between the expected decimal value and the actual null result.

The issue occurs when:

  1. A ChunkedArray contains DecimalArray chunks with very large i256 values
  2. Multiple Sum operations are performed sequentially
  3. The accumulated sum exceeds i256::MAX, causing CheckedAdd to return None
  4. The sum function correctly returns Scalar::null() on overflow
  5. The fuzzer expects the computed sum but gets null instead

This is a test infrastructure issue rather than a bug in the sum implementation. The fuzzer should either:

  • Detect when overflow would occur and adjust expectations
  • Verify that null is returned when overflow happens
  • Generate input values that won't overflow
Debug Output
FuzzArrayAction {
    array: ChunkedArray {
        dtype: Decimal(
            DecimalDType {
                precision: 76,
                scale: 75,
            },
            Nullable,
        ),
        len: 12,
        chunks: [
            DecimalArray { ... values_type: I256, validity: AllValid ... },
            DecimalArray { ... values_type: I256, validity: AllValid ... }
        ]
    },
    actions: [
        (Sum, Scalar { value: decimal256(27897708223554751832957193840191214563962497566384571035819434488814200889077, precision=76, scale=75) }),
        (Sum, Scalar { value: decimal256(27897708223554751832957193840191214563962497566384571035819434488814200889077, precision=76, scale=75) }),
        (Sum, Scalar { value: decimal256(27897708223554751832957193840191214563962497566384571035819434488814200889077, precision=76, scale=75) }),
        (Sum, Scalar { value: decimal256(27897708223554751832957193840191214563962497566384571035819434488814200889077, precision=76, scale=75) })
    ]
}

Summary

Reproduction

  1. Download the crash artifact:

  2. Reproduce locally:

# The artifact contains array_ops/crash-0171cbd8eede2afdec81571443c1aa8ff4e52032
cargo +nightly fuzz run -D --sanitizer=none array_ops array_ops/crash-0171cbd8eede2afdec81571443c1aa8ff4e52032 -- -rss_limit_mb=0
  1. Get full backtrace:
RUST_BACKTRACE=full cargo +nightly fuzz run -D --sanitizer=none array_ops array_ops/crash-0171cbd8eede2afdec81571443c1aa8ff4e52032 -- -rss_limit_mb=0

Auto-created by fuzzing workflow with Claude analysis

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