You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fix unsound lifetime extension in HRTB function pointer coercion
Fixes#25860
= Problem =
The compiler allowed unsound coercions from function items/pointers with
nested reference parameters to HRTB function pointers, enabling arbitrary
lifetime extension to 'static. This was demonstrated by the cve-rs exploit:
```rust
fn foo<'a, 'b, T>(_: &'a &'b (), v: &'b T) -> &'a T { v }
// This coercion was allowed but unsound:
let f: for<'x> fn(_, &'x T) -> &'static T = foo;
```
The issue occurs because nested references like `&'a &'b ()` create an
implied outlives bound `'b: 'a`. When coercing to an HRTB function pointer,
this constraint was not validated, allowing the inner lifetime to be
extended arbitrarily.
= Solution =
This commit adds validation during function pointer coercion to detect and
reject unsound HRTB coercions involving implied bounds from nested references.
The fix works in two stages:
1. Extract implied outlives bounds from nested references in the source
function signature using a new `implied_bounds` module in rustc_infer.
2. During HRTB function pointer coercion in rustc_hir_typeck, check if:
- Source has nested references with implied bounds
- Target does NOT preserve the nested reference structure
- If both conditions hold, reject the coercion as unsound
This refined approach allows safe coercions like:
`fn(&'a &'b T) -> for<'r, 's> fn(&'r &'s T)` (preserves structure)
While blocking unsound ones like:
`fn(&'a &'b T) -> for<'r> fn(&'r T)` (collapses lifetimes)
== Implementation Details ==
New module: `compiler/rustc_infer/src/infer/outlives/implied_bounds.rs`
- `extract_nested_reference_bounds()`: Recursively extracts implied bounds
from nested references, tuples, and ADT type arguments
Modified: `compiler/rustc_hir_typeck/src/coercion.rs`
- `check_hrtb_implied_bounds()`: Validates HRTB coercions in both
`coerce_from_fn_pointer()` and `coerce_from_fn_item()`
- Only rejects when nested reference structure is not preserved in target
== Testing ==
- Added comprehensive test: `tests/ui/implied-bounds/cve-rs-lifetime-expansion.rs`
reproducing and validating the fix for the cve-rs exploit
- Updated multiple existing tests to reflect corrected behavior
- All 19,700+ UI tests pass with only 1 unrelated platform-specific failure
- Verified no regressions in common patterns and real-world crate usage (e.g., syn)
== Notes ==
This fix is conservative but precise; it only rejects coercions that would
violate soundness by collapsing nested lifetime relationships. Valid code
patterns, even those using nested references with HRTB, continue to compile.
The fix addresses the specific exploit in #25860 (cve-rs
lifetime expansion) and is distinct from the related but separate issue
#84591 (HRTB on subtraits).
0 commit comments