gpui_windows: Fix use-after-free in power request reason string (#64001)
## Summary
`PowerRequest::prevent_idle_sleep` passed `PowerCreateRequest` a reason
string whose UTF-16 buffer was dropped when the function returned.
`PowerCreateRequest` documents that the reason pointer must remain valid
for the lifetime of the handle, so the OS was left holding a pointer
into freed memory.
This is a use-after-free (CWE-416), a memory-safety vulnerability. The
reason string is a fixed literal rather than attacker-controlled input,
so the practical exploitability is limited; but it is a genuine
memory-safety defect and should be fixed.
Keep the UTF-16 buffer alive alongside the handle.
## The bug
The reason string is encoded into a local `Vec<u16>`, and a raw pointer
to its heap buffer is handed to `PowerCreateRequest`:
```rust
let mut reason = reason.encode_utf16().chain([0]).collect::<Vec<_>>();
let context = REASON_CONTEXT {
// ...
Reason: REASON_CONTEXT_0 {
SimpleReasonString: PWSTR(reason.as_mut_ptr()),
},
};
let handle = unsafe { PowerCreateRequest(&context) }?;
// ...
Ok(Self { handle }) // `reason` dropped here, freeing the buffer the handle points into
```
The pointer crosses an `unsafe` FFI boundary, so the borrow checker
cannot see that Windows retains it. When `prevent_idle_sleep` returns,
`reason` is dropped and its buffer freed while the handle still refers
to it.
## The fix
Move the UTF-16 buffer into the struct so it lives as long as the
handle:
```rust
struct PowerRequest {
handle: HANDLE,
_reason: Vec<u16>,
}
// ...
Ok(Self { handle, _reason: reason })
```
`Drop` closes the handle before fields are dropped, so the buffer is
freed only after the OS stops referencing it.
Release Notes:
- Fixed a use-after-free in Windows idle-sleep prevention that could
read freed memory.
d2074f4e15whitecat1331 committed on 9/11/2026, 9:17:45 PM· committed by GitHubparentfb38178