Security: SIGSEGV (memory corruption / DoS) parsing untrusted parquet — cencoding.read_rle width overflow
Affected: fastparquet (pip). Verified on 2026.5.0 (aarch64, Python 3.12, pristine wheel); likely earlier versions through the same Cython path. Not specific to platform per mechanism; verifier should reconfirm x86_64.
Summary: fastparquet/cencoding.pyx (compiled boundscheck=False, wraparound=False, cdivision=True) fails to bound the RLE width/length before decoding. For RLE / RLE_DICTIONARY encoded columns, bit_width is taken from the file-controlled schema element type_length and passed unvalidated into read_rle_bit_packed_hybrid → read_rle, which with a huge width, a short page blob, and a small output buffer reads/writes out of bounds and segfaults (SIGSEGV, exit 139). Reachable purely from a crafted .parquet file via fastparquet.ParquetFile(fn).to_pandas() — memory corruption + DoS on untrusted parquet ingest (ETL/gateway/validation boundaries).
Repro (3x each):
- Direct primitive:
import fastparquet.cencoding as ce
ce.read_rle(ce.NumpyIO(bytearray(bytes.fromhex("6ee9f7b8e80f1256b043"))), 31, 0x7fffffff, ce.NumpyIO(bytearray([0]*256)))
# -> process exits 139 (SIGSEGV)
- Crafted file (
crafted-1668.parquet, 2210 B, RLE column type_length patched to 0x7fffffff, short page):
from fastparquet import ParquetFile
ParquetFile("crafted-1668.parquet").to_pandas() # -> process exits 139 (SIGSEGV)
- Control: a normal parquet reads cleanly (
ParquetFile(seed).to_pandas() returns rows) — not a false positive.
Impact: hard SIGSEGV (not a raised exception), out-of-bounds read/write class; DoS + memory-corruption potential on untrusted input.
Suggested fix: validate/clamp width (type_length, per-page bit_width, num_values) against buffer and output bounds before entering the C decode loop.
PoC file attached here (2210 B) or at the reporter's disposal; a private GHSA draft is also prepared and can be raised by a maintainer (or when I have write/admin rights).
Security: SIGSEGV (memory corruption / DoS) parsing untrusted parquet — cencoding.read_rle width overflow
Affected: fastparquet (pip). Verified on 2026.5.0 (aarch64, Python 3.12, pristine wheel); likely earlier versions through the same Cython path. Not specific to platform per mechanism; verifier should reconfirm x86_64.
Summary:
fastparquet/cencoding.pyx(compiledboundscheck=False, wraparound=False, cdivision=True) fails to bound the RLE width/length before decoding. For RLE / RLE_DICTIONARY encoded columns,bit_widthis taken from the file-controlled schema elementtype_lengthand passed unvalidated intoread_rle_bit_packed_hybrid→read_rle, which with a huge width, a short page blob, and a small output buffer reads/writes out of bounds and segfaults (SIGSEGV, exit 139). Reachable purely from a crafted.parquetfile viafastparquet.ParquetFile(fn).to_pandas()— memory corruption + DoS on untrusted parquet ingest (ETL/gateway/validation boundaries).Repro (3x each):
crafted-1668.parquet, 2210 B, RLE columntype_lengthpatched to0x7fffffff, short page):ParquetFile(seed).to_pandas()returns rows) — not a false positive.Impact: hard SIGSEGV (not a raised exception), out-of-bounds read/write class; DoS + memory-corruption potential on untrusted input.
Suggested fix: validate/clamp
width(type_length, per-pagebit_width,num_values) against buffer and output bounds before entering the C decode loop.PoC file attached here (2210 B) or at the reporter's disposal; a private GHSA draft is also prepared and can be raised by a maintainer (or when I have write/admin rights).