Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

LibGit2Sharp.Repository.Lookup sometimes throw LibGit2SharpException #356

Closed
KindDragon opened this Issue · 19 comments

5 participants

@KindDragon

LibGit2Sharp.Repository.Lookup sometimes throw exception with correct input because git_object_lookup return error code -6 (GitErrorCode.Buffer)

Callstack:

LibGit2Sharp.dll!LibGit2Sharp.Core.Ensure.HandleError(int result) Line 77 + 0x56 bytes C#
LibGit2Sharp.dll!LibGit2Sharp.Core.Ensure.ZeroResult(int result) Line 96 + 0x9 bytes C#
LibGit2Sharp.dll!LibGit2Sharp.Core.Proxy.git_object_lookup(LibGit2Sharp.Core.Handles.RepositorySafeHandle repo, LibGit2Sharp.ObjectId id, LibGit2Sharp.GitObjectType type) Line 955 + 0x8 bytes C#
LibGit2Sharp.dll!LibGit2Sharp.Repository.LookupInternal(LibGit2Sharp.ObjectId id, LibGit2Sharp.GitObjectType type, LibGit2Sharp.Core.FilePath knownPath) Line 370 + 0x15 bytes C#
LibGit2Sharp.dll!LibGit2Sharp.Repository.Lookup(LibGit2Sharp.ObjectId id, LibGit2Sharp.GitObjectType type) Line 359 + 0x17 bytes C#
LibGit2Sharp.dll!LibGit2Sharp.DirectReference..ctor.AnonymousMethod__4() Line 21 + 0x2f bytes C#
LibGit2Sharp.dll!LibGit2Sharp.Core.Compat.Lazy.Evaluate() Line 45 + 0x23 bytes C#
LibGit2Sharp.dll!LibGit2Sharp.Core.Compat.Lazy.Value.get() Line 34 + 0xb bytes C#
LibGit2Sharp.dll!LibGit2Sharp.DirectReference.Target.get() Line 29 + 0x21 bytes C#
LibGit2Sharp.dll!LibGit2Sharp.ReferenceWrapper.RetrieveTargetObject(LibGit2Sharp.Reference reference) Line 95 + 0x13 bytes C#
LibGit2Sharp.dll!LibGit2Sharp.ReferenceWrapper..ctor.AnonymousMethod__0() Line 44 + 0x17 bytes C#
LibGit2Sharp.dll!LibGit2Sharp.Core.Compat.Lazy.Evaluate() Line 45 + 0x23 bytes C#
LibGit2Sharp.dll!LibGit2Sharp.Core.Compat.Lazy.Value.get() Line 34 + 0xb bytes C#
LibGit2Sharp.dll!LibGit2Sharp.ReferenceWrapper.TargetObject.get() Line 77 + 0x21 bytes C#
LibGit2Sharp.dll!LibGit2Sharp.Branch.Tip.get() Line 158 + 0xb bytes C#

Lookup called with id b50df60fbeda947afd27331d9ddd2c0a31073f94

$ git branch -a --contains b50df60fbeda947afd27331d9ddd2c0a31073f94
  LibGit2SharpRevisionGridTest
  remotes/origin/LibGit2SharpRevisionGridTest

Next call git_object_lookup throw "An unhandled exception of type 'System.AccessViolationException' occurred in LibGit2Sharp.dll"

@KindDragon

Sorry, this is git2.dll heap corruption

This may be due to a corruption of the heap, which indicates a bug in GitExtensions.exe or any of the DLLs it has loaded.

Callstack:

ntdll.dll!RtlpBreakPointHeap()  + 0x1d bytes    
ntdll.dll!string "(ROUND_UP_TO_POWER2(Size, PAGE_S"...()  - 0xe4ff bytes    
ntdll.dll!RtlValidateHeap()  + 0xb0 bytes   
KernelBase.dll!HeapValidate()  + 0xa bytes  
git2.dll!_CrtIsValidHeapPointer(const void * pUserData)  Line 2036  C++
git2.dll!_free_dbg_nolock(void * pUserData, int nBlockUse)  Line 1322 + 0xa bytes   C++
git2.dll!_free_dbg(void * pUserData, int nBlockUse)  Line 1265 + 0xe bytes  C++
>git2.dll!free(void * pUserData)  Line 50   C++
git2.dll!set_error(int error_class, char * string)  Line 28 C
git2.dll!giterr_set(int error_class, const char * string, ...)  Line 75 C
git2.dll!git_futils_open_ro(const char * path)  Line 93 C
git2.dll!git_futils_readbuffer_updated(git_buf * buf, const char * path, __int64 * mtime, unsigned __int64 * size, int * updated)  Line 157 + 0xd bytes C
git2.dll!reference_read(git_buf * file_content, __int64 * mtime, const char * repo_path, const char * ref_name, int * updated)  Line 127 + 0x24 bytes   C
git2.dll!loose_lookup(git_reference * ref)  Line 207 + 0x39 bytes   C
git2.dll!reference_lookup(git_reference * ref)  Line 982 + 0xa bytes    C
git2.dll!git_reference_lookup_resolved(git_reference * * ref_out, git_repository * repo, const char * name, int max_nesting)  Line 1142 + 0xa bytes C
git2.dll!git_reference_lookup(git_reference * * ref_out, git_repository * repo, const char * name)  Line 1079   C
[Managed to Native Transition]
LibGit2Sharp.dll!LibGit2Sharp.Core.Proxy.git_reference_lookup(LibGit2Sharp.Core.Handles.RepositorySafeHandle repo, string name, bool shouldThrowIfNotFound) Line 1172 + 0x11 bytes  C#
@nulltoken
Owner

@KindDragon Hmm. This is the kind of bug I'd really like to fix.

However, I'm not sure to understand how to reproduce it.
It would be awesome if you could help me and describe the steps I should follow in order to make this fail?

@KindDragon

I can reproduce with our build of GitExtensions from LibGit2Sharp, but I could not create a minimal test that reproduces this bug.

This may be due to a corruption of the heap, which indicates a bug in GitExtensions.exe or any of the DLLs it has loaded.

@XaeroDegreaz

I have this issue as well. I've had to use the version before the last packaging of the new git2.dll binaries.

@nulltoken
Owner

@KindDragon @XaeroDegreaz Do you think you could come up with some C# code that could put this issue under the light? I'd be more than happy to fix this for you.

@KindDragon

I think this is problem with multi-threading, after I wrap all calls to LibGit2Sharp with one lock this bug go away.

@nulltoken
Owner

Some changes have been merged in libgit2 in order to improve the thread safety. Could you please try and remove the lock() statement and check if the Exception is no longer thrown?

@KindDragon

It's help with exception, but heap corruption is still reproducible
shot_17062013_25427

@nulltoken
Owner

Hmmm. Do you think you create a striped down console app which could reproduce this?

@nulltoken
Owner

@arrbee I wonder if the following change at errors.c:26 would solve the issue

if (error->message != NULL)
   git__free(error->message);
@nulltoken
Owner

@arrbee Hmm. No. My previous message makes very little sense.

@nulltoken
Owner

FWIW, the git2-9d9fff3.dll binary is embedded in the vNext branch.

It's been compiled with the UpdateLibgit2ToSha.ps1 script which leverages the -D THREADSAFE=ON build flag.

/cc @ben

@arrbee
Owner

Let me open a libgit2 PR that makes set_error() threadsafe. It currently isn't and with git__compare_and_swap it will not be hard to fix.

@arrbee
Owner

No wait, that makes no sense. This code uses thread-local storage.

Is it possible that this code is being run in a threaded environment yet git_threads_init() has not been called?

@nulltoken
Owner

Is it possible that this code is being run in a threaded environment yet git_threads_init() has not been called?

@arrbee I doubt it. git_threads_init() is invoked by the NativeMethod static constructor. This should ensure that this is called before any other libgit2 method invokation.

@phkelley @xpaulbettsx Could you please confirm this? ^^

@phkelley
Collaborator

That's right, @nulltoken. If there is heap corruption occurring then I recommend running the application with "full page heap" enabled. This setting causes Windows to allocate at least 2 pages for every memory allocation. The requested bytes are stuffed at the end of the 1st page, so that if the buffer is overrun, the first byte of the overrun lands on the 2nd page. The 2nd page is marked no-access; any attempt to read or write from it will cause the CPU to raise an access violation exception. This special heap causes the application to run very slowly, but it catches many heap corruptions as they happen, rather than when the corruption causes a problem down the line and you can't find out why.

This setting can be enabled using the Global Flags tool available with WinDbg, which is part of the Windows SDK.

@nulltoken
Owner

@KindDragon Have you recently been able to reproduce this heap corruption?

@KindDragon

I cannot reproduce it with latest build

@nulltoken
Owner

I cannot reproduce it with latest build

Thanks @KindDragon. I'm going to close this one for now, then. Please, feel free to reopen it if this heap corruption sneaks out again.

@nulltoken nulltoken closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.