wincred
wincred copied to clipboard
Unsafe syscall usage, may cause random panic (very rarely)
procCredWrite proc = modadvapi32.NewProc("CredWriteW")
procCredDelete proc = modadvapi32.NewProc("CredDeleteW")
procCredFree proc = modadvapi32.NewProc("CredFree")
Go use //go:uintptrescapes to make uintptr(unsafe.Pointer(pcred)) in procCredDelete.Call(...)(Proc.Call) argument list safe by:
- Enforce
pcredescape to heap; - Keep
pcredalive during the call.
src\syscall\dll_windows.go:
// Call executes procedure p with arguments a.
//
// The returned error is always non-nil, constructed from the result of GetLastError.
// Callers must inspect the primary return value to decide whether an error occurred
// (according to the semantics of the specific function being called) before consulting
// the error. The error always has type [Errno].
//
// On amd64, Call can pass and return floating-point values. To pass
// an argument x with C type "float", use
// uintptr(math.Float32bits(x)). To pass an argument with C type
// "double", use uintptr(math.Float64bits(x)). Floating-point return
// values are returned in r2. The return value for C type "float" is
// [math.Float32frombits](uint32(r2)). For C type "double", it is
// [math.Float64frombits](uint64(r2)).
//
//go:uintptrescapes
func (p *Proc) Call(a ...uintptr) (uintptr, uintptr, error) {
return SyscallN(p.Addr(), a...)
}
But the proc interface indirection break this safety guarantee, compiler can't see the //go:uintptrescapes at procCredDelete.Call.
runtime.KeepAlive wont work if the pcred is alloc in the stack, stack grow will change its address, the C api gonna receive a wrong address.