fix(windows): read DACL and ACE headers through owned descriptor storage

CodeQL rust/access-invalid-pointer alerts #551 and #552 (windows.rs) flagged
the header reads in SecurityDescriptor::from_storage: they dereferenced the
pointers GetSecurityDescriptorDacl and GetAce write into null-initialized
out-parameters. The reads were already bounded (null check, then checked
offsets inside the owned descriptor), but the provenance was the FFI
out-pointer. Rebuild both pointers from the owned Vec storage plus the
already-validated acl_offset/entry_offset — the same addresses, matching
the existing acl() accessor — so every dereference is provably inside
owned memory. Behavior is unchanged.

Validation: cargo check -p codewhale-tui --lib --tests --all-features
--locked --target x86_64-pc-windows-gnu: Finished, no errors; rustfmt
--check clean. Hosted CodeQL and Windows tests are the proof.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Signed-off-by: CodeWhale Bot <[email protected]>
This commit is contained in:
CodeWhale BotandClaude Opus 5.5 committed 2026-10-04 15:34:50 -07:00
1 parent 5f88941a7d
commit 561de7c753
1 file changed
+9
+9
View File
@@ -1474,6 +1474,12 @@ impl RawDacl {
.is_some_and(|end| end <= length)
})
.ok_or_else(|| io::Error::other("DACL header is outside its descriptor"))?;
// Read through owned storage at the checked offset, not through the
// out-pointer Windows returned: same address, owned provenance.
// SAFETY: acl_offset + size_of::<ACL>() <= length <= storage bytes.
let acl = unsafe { storage.as_ptr().cast::<u8>().add(acl_offset) }
.cast_mut()
.cast::<ACL>();
// SAFETY: the aligned DACL header lies completely inside storage.
let acl_size = usize::from(unsafe { (*acl).AclSize });
if acl_size < size_of::<ACL>()
@@ -1505,6 +1511,9 @@ impl RawDacl {
.is_some_and(|end| end <= acl_size)
})
.ok_or_else(|| io::Error::other("ACE header is outside its DACL"))?;
// Same rule: address the ACE from the storage-derived ACL.
// SAFETY: entry_offset + size_of::<ACE_HEADER>() <= acl_size.
let entry = unsafe { acl.cast::<u8>().add(entry_offset) };
// SAFETY: the complete, aligned ACE header is inside the DACL.
let header = unsafe { &*entry.cast::<ACE_HEADER>() };
let entry_size = usize::from(header.AceSize);