Description
Summary
GitPushOptions
(CS) signature mismatch with git_push_options
(C) causes uninitialized memory and access violation when calling git_remote_push
in libgit2 when credentials are passed for accessing a private repo. The custom_headers
member of git_push_options
points to random garbage after the call is marshalled because the corresponding member is missing from GitPushOptions
.
As a side note, GitHub Desktop cannot push to our private repo, but it doesn't report anything useful when it fails. I imagine this is the cause.
To Reproduce:
Using commit 9d17afe (Oct 23) I'm trying to push using the following code. I'm pushing to a private repo on GitHub using username/personal access token
pair.
if (string.IsNullOrWhiteSpace(Branch))
Branch = "master";
using (var repo = new Repository(WorkingTree))
{
Log.LogMessage("Pushing branch '{0}' from '{1}'", Branch, WorkingTree);
LibGit2Sharp.PushOptions options = new LibGit2Sharp.PushOptions();
options.CredentialsProvider = (_url, _user, _cred) => new UsernamePasswordCredentials { Username = Username, Password = Password };
var branch = repo.Branches[Branch];
lock (m_lock)
{
repo.Network.Push(branch, options);
}
}
return true;
This results in a 'System.AccessViolationException'.
Details
Debugging into this, I see that git_remote_push
on line 2450 of remote.c takes git_push_options
as a parameter. From remote.h:
/**
* Controls the behavior of a git_push object.
*/
typedef struct {
unsigned int version;
/**
* If the transport being used to push to the remote requires the creation
* of a pack file, this controls the number of worker threads used by
* the packbuilder when creating that pack file to be sent to the remote.
*
* If set to 0, the packbuilder will auto-detect the number of threads
* to create. The default value is 1.
*/
unsigned int pb_parallelism;
/**
* Callbacks to use for this push operation
*/
git_remote_callbacks callbacks;
/**
* Extra headers for this push operation
*/
git_strarray custom_headers;
} git_push_options;
The corresponding C# type is GitPushOptions
defined as
namespace LibGit2Sharp.Core
{
[StructLayout(LayoutKind.Sequential)]
internal class GitPushOptions
{
public int Version = 1;
public int PackbuilderDegreeOfParallelism;
public GitRemoteCallbacks RemoteCallbacks;
}
}
Notice that GitPushOptions
is missing the custom_headers
member.