Skip to content

Fix access violations when cloning/fetching via HTTPS #38

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

Merged
merged 3 commits into from
Mar 20, 2015
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 58 additions & 7 deletions compat/mingw.c
Original file line number Diff line number Diff line change
Expand Up @@ -966,6 +966,10 @@ static int do_putenv(char **env, const char *name, int size, int free_old);
static int environ_size = 0;
/* allocated size of environ array, in bytes */
static int environ_alloc = 0;
/* used as a indicator when the environment has been changed outside mingw.c */
static char **saved_environ;

static void maybe_reinitialize_environ(void);

/*
* Create environment block suitable for CreateProcess. Merges current
Expand All @@ -975,21 +979,24 @@ static wchar_t *make_environment_block(char **deltaenv)
{
wchar_t *wenvblk = NULL;
char **tmpenv;
int i = 0, size = environ_size, wenvsz = 0, wenvpos = 0;
int i = 0, size, wenvsz = 0, wenvpos = 0;

maybe_reinitialize_environ();
size = environ_size;

while (deltaenv && deltaenv[i])
while (deltaenv && deltaenv[i] && *deltaenv[i])
i++;

/* copy the environment, leaving space for changes */
tmpenv = xmalloc((size + i) * sizeof(char*));
memcpy(tmpenv, environ, size * sizeof(char*));

/* merge supplied environment changes into the temporary environment */
for (i = 0; deltaenv && deltaenv[i]; i++)
for (i = 0; deltaenv && deltaenv[i] && *deltaenv[i]; i++)
size = do_putenv(tmpenv, deltaenv[i], size, 0);

/* create environment block from temporary environment */
for (i = 0; tmpenv[i]; i++) {
for (i = 0; tmpenv[i] && *tmpenv[i]; i++) {
size = 2 * strlen(tmpenv[i]) + 2; /* +2 for final \0 */
ALLOC_GROW(wenvblk, (wenvpos + size) * sizeof(wchar_t), wenvsz);
wenvpos += xutftowcs(&wenvblk[wenvpos], tmpenv[i], size) + 1;
Expand Down Expand Up @@ -1278,6 +1285,41 @@ static int compareenv(const void *v1, const void *v2)
}
}

/*
* Functions implemented outside Git are able to modify the environment,
* too. For example, cURL's curl_global_init() function sets the CHARSET
* environment variable (at least in certain circumstances).
*
* Therefore we need to be *really* careful *not* to assume that we have
* sole control over the environment and reinitalize it when necessary.
*/
static void maybe_reinitialize_environ(void)
{
int i;

if (!saved_environ) {
warning("MinGW environment not initialized yet");
return;
}

if (environ_size <= 0)
return;

if (saved_environ != environ)
/* We have *no* idea how much space was allocated outside */
environ_alloc = 0;
else if (!environ[environ_size - 1])
return; /* still consistent */

for (i = 0; environ[i] && *environ[i]; i++)
; /* continue counting */
environ[i] = NULL;
environ_size = i + 1;

/* sort environment for O(log n) getenv / putenv */
qsort(environ, i, sizeof(char*), compareenv);
}

static int bsearchenv(char **env, const char *name, size_t size)
{
unsigned low = 0, high = size;
Expand All @@ -1301,7 +1343,7 @@ static int bsearchenv(char **env, const char *name, size_t size)
*/
static int do_putenv(char **env, const char *name, int size, int free_old)
{
int i = bsearchenv(env, name, size - 1);
int i = size <= 0 ? -1 : bsearchenv(env, name, size - 1);

/* optionally free removed / replaced entry */
if (i >= 0 && free_old)
Expand All @@ -1326,7 +1368,14 @@ static int do_putenv(char **env, const char *name, int size, int free_old)
char *mingw_getenv(const char *name)
{
char *value;
int pos = bsearchenv(environ, name, environ_size - 1);
int pos;

if (environ_size <= 0)
return NULL;

maybe_reinitialize_environ();
pos = bsearchenv(environ, name, environ_size - 1);

if (pos < 0)
return NULL;
value = strchr(environ[pos], '=');
Expand All @@ -1335,7 +1384,9 @@ char *mingw_getenv(const char *name)

int mingw_putenv(const char *namevalue)
{
maybe_reinitialize_environ();
ALLOC_GROW(environ, (environ_size + 1) * sizeof(char*), environ_alloc);
saved_environ = environ;
environ_size = do_putenv(environ, namevalue, environ_size, 1);
return 0;
}
Expand Down Expand Up @@ -2223,7 +2274,7 @@ void mingw_startup()
*/
environ_size = i + 1;
environ_alloc = alloc_nr(environ_size * sizeof(char*));
environ = malloc_startup(environ_alloc);
saved_environ = environ = malloc_startup(environ_alloc);

/* allocate buffer (wchar_t encodes to max 3 UTF-8 bytes) */
maxlen = 3 * maxlen + 1;
Expand Down