-
Notifications
You must be signed in to change notification settings - Fork 125
Description
Fuzzing Crash Report
Analysis
Crash Location: vortex-array/src/serde.rs:170 in the ArrayNodeFlatBuffer::try_new function
Error Message:
file write should succeed in fuzz test:
Array vortex.filter does not support serialization
Stack Trace:
0: std::backtrace_rs::backtrace::libunwind::trace
1: std::backtrace_rs::backtrace::trace_unsynchronized
2: <std::backtrace::Backtrace>::create
3: try_new at ./vortex-array/src/serde.rs:170:17
4: serialize at ./vortex-array/src/serde.rs:121:20
5: {async_block#0} at ./vortex-layout/src/layouts/flat/writer.rs:126:29
6: poll
7: {async_block#0} at ./vortex-layout/src/layouts/chunked/writer.rs:79:26
Root Cause:
The fuzzer discovered that FilterArray (encoding ID: vortex.filter) explicitly does not support serialization. When attempting to write an array containing a FilterArray to a file, the serialization check at vortex-array/src/serde.rs:168-174 fails:
for child in array.depth_first_traversal() {
if child.metadata()?.is_none() {
vortex_bail!(
"Array {} does not support serialization",
child.encoding_id()
);
}
}Looking at vortex-array/src/arrays/filter/vtable.rs:70-72, FilterArray's serialization method explicitly returns None:
fn serialize(_metadata: Self::Metadata) -> VortexResult<Option<Vec<u8>>> {
Ok(None)
}And the deserialize method at line 74-76 bails:
fn deserialize(_bytes: &[u8]) -> VortexResult<Self::Metadata> {
vortex_bail!("Filter array is not serializable")
}Array Structure:
- ChunkedArray with dtype I8 Nullable, length 16
- 2 primitive chunks (lengths 15 and 1)
- All validity is either AllInvalid or AllValid
- No projection or filter expressions applied
Impact: FilterArray is an internal/transient array type that should be executed/canonicalized before serialization. The fuzzer exposed a code path where a FilterArray reaches the serialization layer without being executed first.
Debug Output
FuzzFileAction {
array: ChunkedArray {
dtype: Primitive(
I8,
Nullable,
),
len: 16,
chunk_offsets: PrimitiveArray {
dtype: Primitive(
U64,
NonNullable,
),
buffer: BufferHandle(
Host(
Buffer<u8> {
length: 24,
alignment: Alignment(
8,
),
as_slice: [0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, ...],
},
),
),
validity: NonNullable,
stats_set: ArrayStats {
inner: RwLock {
data: StatsSet {
values: [],
},
},
},
},
chunks: [
PrimitiveArray {
dtype: Primitive(
I8,
Nullable,
),
buffer: BufferHandle(
Host(
Buffer<u8> {
length: 15,
alignment: Alignment(
1,
),
as_slice: [255, 109, 109, 109, 109, 255, 109, 102, 109, 109, 109, 37, 4, 157, 85],
},
),
),
validity: AllInvalid,
stats_set: ArrayStats {
inner: RwLock {
data: StatsSet {
values: [],
},
},
},
},
PrimitiveArray {
dtype: Primitive(
I8,
Nullable,
),
buffer: BufferHandle(
Host(
Buffer<u8> {
length: 1,
alignment: Alignment(
1,
),
as_slice: [85],
},
),
),
validity: AllValid,
stats_set: ArrayStats {
inner: RwLock {
data: StatsSet {
values: [],
},
},
},
},
],
stats_set: ArrayStats {
inner: RwLock {
data: StatsSet {
values: [],
},
},
},
},
projection_expr: None,
filter_expr: None,
compressor_strategy: Default,
}
Summary
- Target:
file_io - Crash File:
crash-552031aaf3fcdc9b7100eefa4eb7bb476c23f38f - Branch: develop
- Commit: d70a1e9
- Crash Artifact: https://github.com/vortex-data/vortex/actions/runs/21412350933/artifacts/5278275425
Reproduction
-
Download the crash artifact:
- Direct download: https://github.com/vortex-data/vortex/actions/runs/21412350933/artifacts/5278275425
- Or find
file_io-crash-artifactsat: https://github.com/vortex-data/vortex/actions/runs/21412350933 - Extract the zip file
-
Reproduce locally:
# The artifact contains file_io/crash-552031aaf3fcdc9b7100eefa4eb7bb476c23f38f
cargo +nightly fuzz run -D --sanitizer=none file_io file_io/crash-552031aaf3fcdc9b7100eefa4eb7bb476c23f38f -- -rss_limit_mb=0- Get full backtrace:
RUST_BACKTRACE=full cargo +nightly fuzz run -D --sanitizer=none file_io file_io/crash-552031aaf3fcdc9b7100eefa4eb7bb476c23f38f -- -rss_limit_mb=0Auto-created by fuzzing workflow with Claude analysis