Skip to content

Commit aaed67f

Browse files
committed
alloc: introduce debug allocators
Instead of tweaking the `stdalloc` allocator when `GIT_DEBUG_STRICT_ALLOC` is defined, actually create a debugging allocator. This allows us to ensure that we are strict about things like not expecting `malloc(0)` to do something useful, but we can also introduce an excessively pedantic `realloc` implementation that _always_ creates a new buffer, throws away its original `ptr`, and overwrites the data that's there with garbage. This may be helpful to identify places that make assumptions about realloc.
1 parent c7af393 commit aaed67f

File tree

4 files changed

+92
-11
lines changed

4 files changed

+92
-11
lines changed

src/util/alloc.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@
88
#include "alloc.h"
99
#include "runtime.h"
1010

11-
#include "allocators/failalloc.h"
1211
#include "allocators/stdalloc.h"
12+
#include "allocators/debugalloc.h"
13+
#include "allocators/failalloc.h"
1314
#include "allocators/win32_leakcheck.h"
1415

1516
/* Fail any allocation until git_libgit2_init is called. */
@@ -88,6 +89,8 @@ static int setup_default_allocator(void)
8889
{
8990
#if defined(GIT_WIN32_LEAKCHECK)
9091
return git_win32_leakcheck_init_allocator(&git__allocator);
92+
#elif defined(GIT_DEBUG_STRICT_ALLOC)
93+
return git_debugalloc_init_allocator(&git__allocator);
9194
#else
9295
return git_stdalloc_init_allocator(&git__allocator);
9396
#endif

src/util/allocators/debugalloc.c

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Copyright (C) the libgit2 contributors. All rights reserved.
3+
*
4+
* This file is part of libgit2, distributed under the GNU GPL v2 with
5+
* a Linking Exception. For full terms see the included COPYING file.
6+
*/
7+
8+
#include "debugalloc.h"
9+
10+
static void *debugalloc__malloc(size_t len, const char *file, int line)
11+
{
12+
void *ptr;
13+
size_t total = len + sizeof(size_t);
14+
15+
GIT_UNUSED(file);
16+
GIT_UNUSED(line);
17+
18+
if (!len || (ptr = malloc(total)) == NULL)
19+
return NULL;
20+
21+
memcpy(ptr, &len, sizeof(size_t));
22+
return ptr + sizeof(size_t);
23+
}
24+
25+
static void *debugalloc__realloc(void *ptr, size_t len, const char *file, int line)
26+
{
27+
void *newptr;
28+
size_t original_len;
29+
size_t total = len + sizeof(size_t);
30+
31+
GIT_UNUSED(file);
32+
GIT_UNUSED(line);
33+
34+
if (!len && !ptr)
35+
return NULL;
36+
37+
if (!len) {
38+
free(ptr - sizeof(size_t));
39+
return NULL;
40+
}
41+
42+
if ((newptr = malloc(total)) == NULL)
43+
return NULL;
44+
45+
if (ptr) {
46+
memcpy(&original_len, ptr - sizeof(size_t), sizeof(size_t));
47+
memcpy(newptr + sizeof(size_t), ptr, min(len, original_len));
48+
49+
memset(ptr - sizeof(size_t), 0xfd, original_len + sizeof(size_t));
50+
free(ptr - sizeof(size_t));
51+
}
52+
53+
memcpy(newptr, &len, sizeof(size_t));
54+
return newptr + sizeof(size_t);
55+
}
56+
57+
static void debugalloc__free(void *ptr)
58+
{
59+
if (!ptr)
60+
return;
61+
62+
free(ptr - sizeof(size_t));
63+
}
64+
65+
int git_debugalloc_init_allocator(git_allocator *allocator)
66+
{
67+
allocator->gmalloc = debugalloc__malloc;
68+
allocator->grealloc = debugalloc__realloc;
69+
allocator->gfree = debugalloc__free;
70+
return 0;
71+
}

src/util/allocators/debugalloc.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
* Copyright (C) the libgit2 contributors. All rights reserved.
3+
*
4+
* This file is part of libgit2, distributed under the GNU GPL v2 with
5+
* a Linking Exception. For full terms see the included COPYING file.
6+
*/
7+
8+
#ifndef INCLUDE_allocators_debugalloc_h__
9+
#define INCLUDE_allocators_debugalloc_h__
10+
11+
#include "git2_util.h"
12+
13+
#include "alloc.h"
14+
15+
int git_debugalloc_init_allocator(git_allocator *allocator);
16+
17+
#endif

src/util/allocators/stdalloc.c

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,6 @@ static void *stdalloc__malloc(size_t len, const char *file, int line)
1212
GIT_UNUSED(file);
1313
GIT_UNUSED(line);
1414

15-
#ifdef GIT_DEBUG_STRICT_ALLOC
16-
if (!len)
17-
return NULL;
18-
#endif
19-
2015
return malloc(len);
2116
}
2217

@@ -25,11 +20,6 @@ static void *stdalloc__realloc(void *ptr, size_t size, const char *file, int lin
2520
GIT_UNUSED(file);
2621
GIT_UNUSED(line);
2722

28-
#ifdef GIT_DEBUG_STRICT_ALLOC
29-
if (!size)
30-
return NULL;
31-
#endif
32-
3323
return realloc(ptr, size);
3424
}
3525

0 commit comments

Comments
 (0)