-
Notifications
You must be signed in to change notification settings - Fork 893
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Consider using SafeHandle in Libgit2Object instead of void* #2111
Comments
We are seeing |
@bording In order to benefit from SafeHandles reliability and security guarantees, the code has to AddRef/Release around all places where it operates on the underlying raw handle. It does not look like that the conversions of SafeHandle to IntPtr like https://github.com/libgit2/libgit2sharp/pull/2127/files#diff-f210a201602dfd11231de2914b00197fa6ae2dd165e88d9f602fbfc950c98082R111 do proper AddRef/Release. As far as a I can tell, the code has the same problems as before since it is not using SafeHandle correctly. |
@jkotas Can you point me to documentation that explains what I need to change? The docs didn't seem to explain anything regarding "proper usage". |
The red Caution box at https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.safehandle.dangerousgethandle?view=net-9.0 describes the problem. https://github.com/dotnet/runtime/blob/09b30a4c0618ff378abd523fd02e113b2474e958/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFString.cs#L56-L78 is a random example of a typical use. |
@jkotas If the derived handle type usage is wrapped in a using statement, is it still also required to pair up For example, this method is using this implicit operator to access the underlying You're saying that's not enough and it also needs to be wrapped in |
If the calling method ensures lifetime like in your example, additional Also, another common pattern is leave it to the P/Invoke marshaller to auto-generate the libgit2sharp/LibGit2Sharp/Core/NativeMethods.cs Lines 241 to 242 in a88e2a0
int git_branch_delete(ReferenceHandle reference); , so that you do not have to write the DangerousAddRef / DangerousRelease manually.
|
I use a disposable struct and an extension method to help with this https://gist.github.com/rickbrew/0c1643b5186f8ac061be092de7a9a40a SafeHandle handle = ...;
using (SafeHandleValue handleValue = handle.UseValue())
{
SomeNativeMethod(handleValue.Value); // or omit .Value and use the implicit cast to `IntPtr` / `nint`
} |
We've had a couple of bug reports against dotnet/runtime with rarely-reproduceable crashes coming from libgit2sharp. We believe that one possible reason could be an interop anti-pattern in Libgit2Object -
void*/IntPtr
representation of a native handle that can be freed in finalizer. E.g. in this case the finalizer in Libgit2Object may end up calling native free here (and other overloads).The reason why it's called an anti-pattern can be explained by a short repro in this issue: dotnet/runtime#103522 and a general solution is to use
SafeHandle
for such handles. Also, see https://learn.microsoft.com/en-us/dotnet/standard/native-interop/best-practicesReproduction steps
Expected behavior
Actual behavior
Version of LibGit2Sharp (release number or SHA1)
Operating system(s) tested; .NET runtime tested
The text was updated successfully, but these errors were encountered: