Skip to content

Firefox crashes when built with LLVM 21, due to llvm/llvm-project#129889 #166870

@steven-michaud

Description

@steven-michaud

I've already commented several times at #129889, so I'll keep my comments here brief.

As promised, I'm submitting copies (lightly edited) of two lldb sessions. One was made running a local trunk build of Firefox made with LLVM 21.1.6 (current code on the release/21.x branch). It shows the crash, and how it was caused by this commit. The second was made running a local trunk build of Firefox made with a patched LLVM 21.1.6 that disables copy propagation, using the first of the three patches here. Everything was done on an M1 Mac Mini running macOS 26.1.

lldb-session-bad.txt
lldb-session-good.txt

The "bad" session crashes. The "good" session doesn't. The only relevant difference between the two builds is that in the "good" one, the stp x8, x9, [sp, #0x28] instruction is preceded by the following two instructions, while in the bad one it isn't. In the "bad" build these two instructions were removed by the copy propagation commit.

mov    w9, w9
mov    w8, w8

The x8 register ends up being used as x in the following code (located here on the Firefox trunk). The nsPNGEncoder::ConvertHostARGBRow() method is inlined inside nsPNGEncoder::AddImageFrame().

for (uint32_t x = 0; x < aPixelWidth; x++) {
  const uint32_t& pixelIn = ((const uint32_t*)(aSrc))[x];
  uint8_t* pixelOut = &aDest[x * pixelStride];

  uint8_t alpha = (pixelIn & 0xff000000) >> 24;
  pixelOut[pixelStride - 1] = alpha;  // overwritten below if pixelStride == 3

  ...

}

In the bad build x8 has junk in its top 32 bits (0x00000030). In the good build it doesn't. The junk makes x8 much larger than it should be, and causes a buffer overflow.

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions