Skip to content

Commit 9a5df16

Browse files
kbleespatthoyts
authored andcommitted
Win32: use low-level memory allocation during initialization
As of d41489a "Add more large blob test cases", git's high-level memory allocation functions (xmalloc, xmemdupz etc.) access the environment to simulate limited memory in tests (see 'getenv("GIT_ALLOC_LIMIT")' in memory_limit_check()). These functions should not be used before the environment is fully initialized (particularly not to initialize the environment itself). The current solution ('environ = NULL; ALLOC_GROW(environ...)') only works because MSVCRT's getenv() reinitializes environ when it is NULL (i.e. it leaves us with two sets of unusabe (non-UTF-8) and unfreeable (CRT- allocated) environments). Add our own set of malloc-or-die functions to be used in startup code. Also check the result of __wgetmainargs, which may fail if there's not enough memory for wide-char arguments and environment. This patch is in preparation of the sorted environment feature, which completely replaces MSVCRT's getenv() implementation. Signed-off-by: Karsten Blees <[email protected]>
1 parent 5140042 commit 9a5df16

File tree

1 file changed

+36
-16
lines changed

1 file changed

+36
-16
lines changed

compat/mingw.c

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2046,16 +2046,37 @@ typedef struct {
20462046
extern int __wgetmainargs(int *argc, wchar_t ***argv, wchar_t ***env, int glob,
20472047
_startupinfo *si);
20482048

2049+
static NORETURN void die_startup()
2050+
{
2051+
fputs("fatal: not enough memory for initialization", stderr);
2052+
exit(128);
2053+
}
2054+
2055+
static void *malloc_startup(size_t size)
2056+
{
2057+
void *result = malloc(size);
2058+
if (!result)
2059+
die_startup();
2060+
return result;
2061+
}
2062+
2063+
static char *wcstoutfdup_startup(char *buffer, const wchar_t *wcs, size_t len)
2064+
{
2065+
len = xwcstoutf(buffer, wcs, len) + 1;
2066+
return memcpy(malloc_startup(len), buffer, len);
2067+
}
2068+
20492069
void mingw_startup()
20502070
{
2051-
int i, len, maxlen, argc;
2071+
int i, maxlen, argc;
20522072
char *buffer;
20532073
wchar_t **wenv, **wargv;
20542074
_startupinfo si;
20552075

20562076
/* get wide char arguments and environment */
20572077
si.newmode = 0;
2058-
__wgetmainargs(&argc, &wargv, &wenv, _CRT_glob, &si);
2078+
if (__wgetmainargs(&argc, &wargv, &wenv, _CRT_glob, &si) < 0)
2079+
die_startup();
20592080

20602081
/* determine size of argv and environ conversion buffer */
20612082
maxlen = wcslen(_wpgmptr);
@@ -2064,26 +2085,25 @@ void mingw_startup()
20642085
for (i = 0; wenv[i]; i++)
20652086
maxlen = max(maxlen, wcslen(wenv[i]));
20662087

2067-
/* nedmalloc can't free CRT memory, allocate resizable environment list */
2068-
environ = NULL;
2088+
/*
2089+
* nedmalloc can't free CRT memory, allocate resizable environment
2090+
* list. Note that xmalloc / xmemdupz etc. call getenv, so we cannot
2091+
* use it while initializing the environment itself.
2092+
*/
20692093
environ_size = i + 1;
2070-
ALLOC_GROW(environ, environ_size * sizeof(char*), environ_alloc);
2094+
environ_alloc = alloc_nr(environ_size * sizeof(char*));
2095+
environ = malloc_startup(environ_alloc);
20712096

20722097
/* allocate buffer (wchar_t encodes to max 3 UTF-8 bytes) */
20732098
maxlen = 3 * maxlen + 1;
2074-
buffer = xmalloc(maxlen);
2099+
buffer = malloc_startup(maxlen);
20752100

20762101
/* convert command line arguments and environment to UTF-8 */
2077-
len = xwcstoutf(buffer, _wpgmptr, maxlen);
2078-
__argv[0] = xmemdupz(buffer, len);
2079-
for (i = 1; i < argc; i++) {
2080-
len = xwcstoutf(buffer, wargv[i], maxlen);
2081-
__argv[i] = xmemdupz(buffer, len);
2082-
}
2083-
for (i = 0; wenv[i]; i++) {
2084-
len = xwcstoutf(buffer, wenv[i], maxlen);
2085-
environ[i] = xmemdupz(buffer, len);
2086-
}
2102+
__argv[0] = wcstoutfdup_startup(buffer, _wpgmptr, maxlen);
2103+
for (i = 1; i < argc; i++)
2104+
__argv[i] = wcstoutfdup_startup(buffer, wargv[i], maxlen);
2105+
for (i = 0; wenv[i]; i++)
2106+
environ[i] = wcstoutfdup_startup(buffer, wenv[i], maxlen);
20872107
environ[i] = NULL;
20882108
free(buffer);
20892109

0 commit comments

Comments
 (0)