Open Bug 2061973 Opened 3 months ago Updated 2 months ago

Crash in [@ zlib_rs::inflate::inflate_fast_help_impl]

Categories

(Core :: General, defect, P3)

defect

Tracking

()

People

(Reporter: calixte, Unassigned)

References

(Blocks 1 open bug)

Details

(Keywords: crash, regression)

Crash Data

Crash report: https://crash-stats.mozilla.org/report/index/5f52ad87-cab1-47a8-bd80-64e110260807

Crash Reason:

EXCEPTION_ACCESS_VIOLATION_WRITE at 0x0000000000000000

Top 10 frames:

0  xul.dll  zlib_rs::inflate::inflate_fast_help_avx2(zlib_rs::inflate::State*, unsigned long...  third_party/rust/zlib-rs/src/inflate.rs:1906
1  xul.dll  zlib_rs::inflate::inflate(zlib_rs::inflate::InflateStream*, zlib_rs::InflateFlus...  third_party/rust/zlib-rs/src/inflate.rs:2407
2  xul.dll  MOZ_PNG_proc_IDAT_data(png_struct_def*, unsigned char*, unsigned long long)  media/libpng/pngpread.c:699
3  xul.dll  mozilla::image::nsPNGDecoder::ReadPNGData(char const*, unsigned long long)  image/decoders/nsPNGDecoder.cpp:436
4  xul.dll  mozilla::image::StreamingLexer<mozilla::image::nsPNGDecoder::State,16>::Continue...  image/StreamingLexer.h:552
5  xul.dll  mozilla::image::nsPNGDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mo...  image/decoders/nsPNGDecoder.cpp:401
6  xul.dll  mozilla::image::Decoder::Decode(mozilla::image::IResumable*)  image/Decoder.cpp:190
7  xul.dll  mozilla::image::DecodedSurfaceProvider::Run()  image/DecodedSurfaceProvider.cpp:123
8  xul.dll  mozilla::image::DecodingTask::Run()  image/DecodePool.cpp:152
9  xul.dll  mozilla::ThreadFuncPoolThread(void*)  xpcom/threads/TaskController.cpp:335

There is 1 crash in nightly 155 with buildid 20260806095421.

Clouseau analysis (confidence probable): The crash is a WRITE to a near-null address (0x50) inside zlib-rs's unsafe AVX2 inflate fast path (inflate_fast_help_impl), whose only safety precondition check (state.bit_reader.bytes_remaining() >= 15) is a debug_assert! that compiles out in release — meaning any caller-side miscalculation of avail_in/avail_out (or a genuine bug in the AVX2 SIMD implementation itself) has no runtime guard before the unsafe write.

dfbb73240fbf (bug 2023197) is the last changeset to touch third_party/rust/zlib-rs/src/inflate.rs, cpu_features.rs, and third_party/rust/libz-rs-sys/src/lib.rs at all — a full 0.6.3 vendoring bump that landed only after two prior land/backout cycles of the same bug, consistent with this being fragile code that a domain owner should re-examine, even though it predates the crash build by ~5 months and I did not verify a specific introduced defect via line diff.

Suspected regressor: dfbb73240fbf (gh) (bug 2023197) by Lars Eggert.

Code references:

:leggert, can you have a look please?

Flags: needinfo?(leggert)
Blocks: clouseau, 2023197

The Bugbug bot thinks this bug should belong to the 'Core::Audio/Video: Playback' component, and is moving the bug to that component. Please correct in case you think the bot is wrong.

Component: General → Audio/Video: Playback
Product: Firefox → Core

:calixte, since this bug is a regression, could you fill (if possible) the regressed_by field?
For more information, please visit BugBot documentation.

Flags: needinfo?(cdenizet)

Analysis

The crashing stack in this report contains no media code. It is zlib-rs inflate called from libpng's IDAT processing inside the ImageLib PNG decoder (MOZ_PNG_proc_IDAT_data -> nsPNGDecoder::ReadPNGData -> image::Decoder::Decode). Comment 1 records that BugBot auto-assigned this to Core::Audio/Video: Playback; that routing looks incorrect.

Suggest Core::General as the destination. ./mach file-info bugzilla-component modules/zlib/ resolves there, and it is also where the previous crash bug for this code (bug 1950764) was tracked and fixed by the zlib-rs integration owner. Core::Graphics: ImageLib would be too narrow: the signature is caller-agnostic and only one of the four reports under it has a PNG stack.

Crash volume

crash-stats SuperSearch for this exact signature, 2026-02-10 to 2026-08-10: 4 reports total, spread over 4 distinct build IDs, 3 platforms (Windows, Linux, Android), 2 channels (release and nightly), both parent and content processes, and 3 different crash reasons. The wider zlib_rs::inflate::* family is 57 reports over the same window across 23 distinct CPU models, with a large share on older parts (Sandy Bridge, Ivy Bridge, Haswell, Broadwell) alongside AMD Zen 1-5. There is no clustering by build, platform, CPU model or microcode version.

On the suspected regressor

The suspected regressor in comment 0 (bug 2023197, the zlib-rs 0.6.3 bump, landed 2026-03-18) does not hold up. crash-stats has zero zlib_rs::inflate::* reports before 2026-03-18 and 57 after, but that step change is explained by bug 2017549, "Enable libz-rs-sys by default on release", which landed 2026-03-26 - eight days later. Before that, libz-rs-sys was nightly-only (bug 1910796, 2025-02-21) and then early-beta (bug 1968103, 2025-05-22). So the apparent correlation is an exposed-population change of several orders of magnitude, not evidence that the 0.6.3 bump introduced a defect. A control query confirms the index does retain data from before that date (MOZ_Z_inflate* returns results in the same window).

Leaving regressed_by unset rather than guessing (this also answers the BugBot request in comment 2). The regression keyword may not be warranted.

Correction to the automated analysis in comment 0

Comment 0 states that the safety precondition for the unsafe fast path is checked only by a debug_assert! that compiles out in release. That is not accurate. The debug_assert!(bit_reader.bytes_remaining() >= 15) inside inflate_fast_help_impl is a redundant internal double-check; the real guard is caller-side and is compiled into release builds, at third_party/rust/zlib-rs/src/inflate.rs:571 and :627:

if avail_in >= INFLATE_FAST_MIN_HAVE && avail_out >= INFLATE_FAST_MIN_LEFT {
    // SAFETY: INFLATE_FAST_MIN_HAVE is enough bytes remaining to satisfy the precondition.
    unsafe { inflate_fast_help(self, 0) };

with INFLATE_FAST_MIN_HAVE = 15 and INFLATE_FAST_MIN_LEFT = 260 (same file, lines 554-555).

So the entry condition was satisfied at the call site, yet the write faulted at 0x50. That points at corrupted State contents rather than a missing bounds check. It also fits the rest of the family, where several reports are controlled Rust panics with garbled values - "index out of bounds: the len is 1332 but the index is 654" and similar - i.e. zlib-rs's own bounds checks catching already-corrupt state.

Taken together (no clustering, wide spread over old hardware, garbled-index panics), this looks like the same memory-corruption class as bug 1950764 rather than a code defect. Note it is not the Raptor Lake cluster: CPU family 6 model 183 does not appear anywhere in the data for this family.

Next steps

:gsvelto, you did the CPU-cluster analysis that identified bug 1950764 as Raptor Lake hardware instability. Could you confirm or refute the reading above - that the zlib_rs::inflate::* family is currently dominated by random memory corruption rather than a zlib-rs defect? If it is corruption, this can likely be tracked alongside bug 1950764 instead of being investigated as a new defect.

If a genuine defect is suspected instead, the useful follow-up is upstream at trifectatechfoundation/zlib-rs, as was done for bug 1950764 (upstream issue 306).

Also note bug 2061975 (zlib_rs::inflate::writer::Writer::copy_match_help), filed the same day from the same automated analysis - same family, and it is currently sitting in Firefox::General.

Severity: -- → S3
Component: Audio/Video: Playback → General
Flags: needinfo?(gsvelto)
Priority: -- → P3
See Also: → 1950764, 2061975, 2017549

0x50 is the offset of the bit_reader field in the State struct, which suggests that the reference to this struct is null, but that should be impossible given the only place where we take that reference if via &mut self. I'd wait for more crashes to end up in Socorro before attempting an analysis to confirm that this isn't a fluke.

Flags: needinfo?(gsvelto)

This bug has been marked as a regression. Setting status flag for Nightly to affected.

Flags: needinfo?(cdenizet)
Flags: needinfo?(leggert)
You need to log in before you can comment on or make changes to this bug.