Rust 1.97.1 Ships Emergency Fix for LLVM Bug That Silently Corrupted Code Since 1.87
Rust shipped an emergency point release fixing an LLVM miscompilation that quietly existed since Rust 1.87 and turned crash-prone after 1.97.0.
Editor's Note ·
- Correction:
- The article quotes the GitHub bug report's environment details as "Rustc version: 1.97.0." The cited issue (rust-lang/rust#159035) does not contain a field called "Rustc version"; its rustc --version --verbose output lists the field as "release: 1.97.0." The version number itself (1.97.0) is correct.
- Correction:
- The article quotes the same GitHub bug report as noting the crash was "also reproduced on beta (1.98.0) and nightly (1.99.0)." The reporter's actual wording is "I checked beta (1.98.0) and nightly (1.99.0) - same result." The underlying fact (the bug also reproduces on beta and nightly) is accurate; the quotation marks should not have been used for this paraphrase.
Overview
The Rust project shipped version 1.97.1 on July 16, 2026, an emergency point release that arrived just seven days after 1.97.0, according to LinuxCompatible. The Rust Blog said plainly that “Rust 1.97.1 fixes a miscompilation in an LLVM optimization,” and added a warning that the problem runs deeper than the latest release: “the underlying miscompilation has been present since at least Rust 1.87,” according to the Rust Blog. As previously reported, 1.97.0 had landed on July 9 with changes to symbol mangling, Cargo warning controls, and linker output; it turned out to also make a long-dormant compiler bug far more dangerous.
What We Know
The root cause traces to how LLVM, the compiler backend Rust relies on, optimizes certain conditional memory reads. LWN.net explained that “some sequences of operations that Rust was emitting was causing LLVM to generate code that incorrectly handled enum discriminants, and would end up reading slightly out of bounds of the enum.” Specifically, the flawed optimization pass “was attempting to turn a sequence of select cond, (load ptr_1), (load ptr_2) into load (select cond, ptr_1, ptr_2),” LWN.net reported. That rewrite is only safe if cond genuinely evaluates to true or false; LWN noted that “if cond is not true or false, but instead poison, the first sequence will evaluate to poison, where as the second sequence will be immediate UB” — undefined behavior that the original, unoptimized code sequence would not have triggered.
For more than two years, that flaw was mostly invisible. Before Rust 1.97.0, an affected read landed “slightly out of bounds of the enum” and, per LWN.net, a discriminant value of 2 “would cause the ‘quiet’ miscompilation” — the stray value went unused because it mapped to a case the program never reached. Rust 1.97.0 changed that dynamic by altering how None variants are represented, and “with the 1.97.0 changes, the -1 discriminant was handled poorly, and would end up getting turned into an offset of 2^32-1,” LWN.net said — turning a harmless nearby read into one landing billions of bytes away, which crashes almost every time.
The fallout surfaced quickly on the Rust issue tracker. A bug report filed against the new release, tracked as issue #159035 on GitHub, reproduced the failure with nested enums and pattern matching compiled under optimization, logging the result as “[1] 112371 segmentation fault (core dumped) ./minimal.” The report listed the environment as “Rustc version: 1.97.0,” “LLVM version: 22.1.6,” and platform “x86_64-unknown-linux-gnu,” and noted the crash was “also reproduced on beta (1.98.0) and nightly (1.99.0).” The Rust team tagged the issue P-critical and I-miscompile — its label for cases where “correct Rust code lowers to incorrect machine code.”
The fix that followed, pull request #159106, was titled simply “Update LLVM,” with a description reading “Backport the fix for #159035.” Because Rust’s compiler vendors its own copy of LLVM, the team couldn’t just wait for an upstream point release: contributor nikic noted in the PR thread: “There won’t be one, as LLVM 22 is EOL and no longer accepts backports.” The patch was merged into Rust’s main branch on July 11 and then approved for both the beta and stable backport channels, landing in Rust 1.97.1 and carrying forward into Rust 1.98.0. The Rust Blog summarized the two-part remedy directly: “We have backported both an LLVM fix and a disable of the underlying change in Rust 1.97.0 of Rust’s generated IR that increased the likelihood of this happening.”
LinuxCompatible advised: “Users should run rustup update stable immediately to patch the issue.”
What We Don’t Know
The sources reviewed do not specify how many real-world crashes or corrupted-output incidents, if any, were traced back to the bug before it was diagnosed, nor do they estimate how many published crates or binaries compiled between Rust 1.87 and 1.97.0 may contain the quieter, pre-1.97.0 form of the miscompilation. None of the sources assign the issue a CVE identifier.