Safe Handle¶
What does this mean ?¶
DangerousGetHandle() exposes a native handle without acquiring a lifetime reference. Another thread may dispose the wrapper while unmanaged code uses the raw value. A recycled handle can then identify a different resource. Microsoft documents these lifetime hazards.
What can happen ?¶
Premature release can cause failures or access to an unintended resource. Consequences depend on the native API and resource; merely calling this method is not proof of a data breach. Ownership mistakes relate to improper resource lifetime control, CWE-664.
Recommendation¶
Prefer a managed API or a P/Invoke signature accepting the appropriate SafeHandle type. When legacy interop requires raw access, acquire and release a lifetime reference reliably. This does not validate native arguments or make an arbitrary pointer safe.
Sample Code¶
These fragments assume a valid, owned SafeHandle handle. NativeRead is a synchronous native call that neither closes nor retains the borrowed handle. No caller may independently close or invalidate it outside the wrapper's ownership contract.
Unprotected lifetime:
NativeRead(handle.DangerousGetHandle());
Bounded legacy interop:
bool added = false;
try
{
handle.DangerousAddRef(ref added);
if (handle.IsInvalid)
throw new InvalidOperationException("Invalid native handle");
NativeRead(handle.DangerousGetHandle());
}
finally
{
if (added) handle.DangerousRelease();
}
Regression test: with a test handle, call Dispose() during NativeRead and assert that final release occurs only after the borrowed operation finishes. Make NativeRead throw and verify release still occurs. A disposed wrapper must fail before native work begins.