Skip to content

Commit

Permalink
wrapper.c: introduce gentle xmallocz that does not die()
Browse files Browse the repository at this point in the history
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Nguyễn Thái Ngọc Duy authored and Junio C Hamano committed Aug 18, 2014
1 parent 41ca19b commit f8bb1d9
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 16 deletions.
1 change: 1 addition & 0 deletions git-compat-util.h
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,7 @@ extern try_to_free_t set_try_to_free_routine(try_to_free_t);
extern char *xstrdup(const char *str);
extern void *xmalloc(size_t size);
extern void *xmallocz(size_t size);
extern void *xmallocz_gently(size_t size);
extern void *xmemdupz(const void *data, size_t len);
extern char *xstrndup(const char *str, size_t len);
extern void *xrealloc(void *ptr, size_t size);
Expand Down
68 changes: 52 additions & 16 deletions wrapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,23 @@ static void do_nothing(size_t size)

static void (*try_to_free_routine)(size_t size) = do_nothing;

static void memory_limit_check(size_t size)
static int memory_limit_check(size_t size, int gentle)
{
static int limit = -1;
if (limit == -1) {
const char *env = getenv("GIT_ALLOC_LIMIT");
limit = env ? atoi(env) * 1024 : 0;
}
if (limit && size > limit)
die("attempting to allocate %"PRIuMAX" over limit %d",
(intmax_t)size, limit);
if (limit && size > limit) {
if (gentle) {
error("attempting to allocate %"PRIuMAX" over limit %d",
(intmax_t)size, limit);
return -1;
} else
die("attempting to allocate %"PRIuMAX" over limit %d",
(intmax_t)size, limit);
}
return 0;
}

try_to_free_t set_try_to_free_routine(try_to_free_t routine)
Expand All @@ -42,11 +49,12 @@ char *xstrdup(const char *str)
return ret;
}

void *xmalloc(size_t size)
static void *do_xmalloc(size_t size, int gentle)
{
void *ret;

memory_limit_check(size);
if (memory_limit_check(size, gentle))
return NULL;
ret = malloc(size);
if (!ret && !size)
ret = malloc(1);
Expand All @@ -55,26 +63,54 @@ void *xmalloc(size_t size)
ret = malloc(size);
if (!ret && !size)
ret = malloc(1);
if (!ret)
die("Out of memory, malloc failed (tried to allocate %lu bytes)",
(unsigned long)size);
if (!ret) {
if (!gentle)
die("Out of memory, malloc failed (tried to allocate %lu bytes)",
(unsigned long)size);
else {
error("Out of memory, malloc failed (tried to allocate %lu bytes)",
(unsigned long)size);
return NULL;
}
}
}
#ifdef XMALLOC_POISON
memset(ret, 0xA5, size);
#endif
return ret;
}

void *xmallocz(size_t size)
void *xmalloc(size_t size)
{
return do_xmalloc(size, 0);
}

static void *do_xmallocz(size_t size, int gentle)
{
void *ret;
if (unsigned_add_overflows(size, 1))
die("Data too large to fit into virtual memory space.");
ret = xmalloc(size + 1);
((char*)ret)[size] = 0;
if (unsigned_add_overflows(size, 1)) {
if (gentle) {
error("Data too large to fit into virtual memory space.");
return NULL;
} else
die("Data too large to fit into virtual memory space.");
}
ret = do_xmalloc(size + 1, gentle);
if (ret)
((char*)ret)[size] = 0;
return ret;
}

void *xmallocz(size_t size)
{
return do_xmallocz(size, 0);
}

void *xmallocz_gently(size_t size)
{
return do_xmallocz(size, 1);
}

/*
* xmemdupz() allocates (len + 1) bytes of memory, duplicates "len" bytes of
* "data" to the allocated memory, zero terminates the allocated memory,
Expand All @@ -96,7 +132,7 @@ void *xrealloc(void *ptr, size_t size)
{
void *ret;

memory_limit_check(size);
memory_limit_check(size, 0);
ret = realloc(ptr, size);
if (!ret && !size)
ret = realloc(ptr, 1);
Expand All @@ -115,7 +151,7 @@ void *xcalloc(size_t nmemb, size_t size)
{
void *ret;

memory_limit_check(size * nmemb);
memory_limit_check(size * nmemb, 0);
ret = calloc(nmemb, size);
if (!ret && (!nmemb || !size))
ret = calloc(1, 1);
Expand Down

0 comments on commit f8bb1d9

Please sign in to comment.