Avoid AbsolutePathBuf::parent() panic under EMFILE by skipping re-absolutization (#12647)

Fixes #12216

Fixes a panic in `AbsolutePathBuf::parent()` when the process hits file
descriptor exhaustion (`EMFILE` / "Too many open files").

### Root cause

`AbsolutePathBuf::parent()` was re-validating the parent path via
`from_absolute_path(...).expect(...)`.

`from_absolute_path()` calls `path_absolutize::absolutize()`, which can
depend on `std::env::current_dir()`. Under `EMFILE`, that can fail,
causing `parent()` to panic even though the parent of an absolute path
is already known.

### Change

- Stop re-absolutizing the result of `self.0.parent()`
- Construct `AbsolutePathBuf` directly from the known parent path
- Keep an invariant check with `debug_assert!(p.is_absolute())`

### Why this is safe

`self` is already an `AbsolutePathBuf`, so `self.0` is
absolute/normalized. The parent of an absolute path is expected to be
absolute, so re-running fallible normalization here is unnecessary and
can introduce unrelated panics.
This commit is contained in:
Eric Traut 2026-02-23 21:59:33 -08:00 committed by GitHub
parent 09a82f364f
commit a4076ab4b1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -69,8 +69,11 @@ impl AbsolutePathBuf {
pub fn parent(&self) -> Option<Self> {
self.0.parent().map(|p| {
#[expect(clippy::expect_used)]
Self::from_absolute_path(p).expect("parent of AbsolutePathBuf must be absolute")
debug_assert!(
p.is_absolute(),
"parent of AbsolutePathBuf must be absolute"
);
Self(p.to_path_buf())
})
}