summaryrefslogtreecommitdiff
path: root/src/allocators/stdalloc.c
blob: 2b36d9f3df3e87641b5efcb9eee9ca56f4ba2e1d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/*
 * Copyright (C) the libgit2 contributors. All rights reserved.
 *
 * This file is part of libgit2, distributed under the GNU GPL v2 with
 * a Linking Exception. For full terms see the included COPYING file.
 */

#include "stdalloc.h"

static void *stdalloc__malloc(size_t len, const char *file, int line)
{
	void *ptr;

	GIT_UNUSED(file);
	GIT_UNUSED(line);

#ifdef GIT_DEBUG_STRICT_ALLOC
	if (!len)
		return NULL;
#endif

	ptr = malloc(len);

	if (!ptr)
		git_error_set_oom();

	return ptr;
}

static void *stdalloc__calloc(size_t nelem, size_t elsize, const char *file, int line)
{
	void *ptr;

	GIT_UNUSED(file);
	GIT_UNUSED(line);

#ifdef GIT_DEBUG_STRICT_ALLOC
	if (!elsize || !nelem)
		return NULL;
#endif

	ptr = calloc(nelem, elsize);

	if (!ptr)
		git_error_set_oom();

	return ptr;
}

static char *stdalloc__strdup(const char *str, const char *file, int line)
{
	char *ptr;

	GIT_UNUSED(file);
	GIT_UNUSED(line);

	ptr = strdup(str);

	if (!ptr)
		git_error_set_oom();

	return ptr;
}

static char *stdalloc__strndup(const char *str, size_t n, const char *file, int line)
{
	size_t length = 0, alloclength;
	char *ptr;

	length = p_strnlen(str, n);

	if (GIT_ADD_SIZET_OVERFLOW(&alloclength, length, 1) ||
	    !(ptr = stdalloc__malloc(alloclength, file, line)))
		return NULL;

	if (length)
		memcpy(ptr, str, length);

	ptr[length] = '\0';

	return ptr;
}

static char *stdalloc__substrdup(const char *start, size_t n, const char *file, int line)
{
	char *ptr;
	size_t alloclen;

	if (GIT_ADD_SIZET_OVERFLOW(&alloclen, n, 1) ||
	    !(ptr = stdalloc__malloc(alloclen, file, line)))
		return NULL;

	memcpy(ptr, start, n);
	ptr[n] = '\0';
	return ptr;
}

static void *stdalloc__realloc(void *ptr, size_t size, const char *file, int line)
{
	void *new_ptr;

	GIT_UNUSED(file);
	GIT_UNUSED(line);

#ifdef GIT_DEBUG_STRICT_ALLOC
	if (!size)
		return NULL;
#endif

	new_ptr = realloc(ptr, size);

	if (!new_ptr)
		git_error_set_oom();

	return new_ptr;
}

static void *stdalloc__reallocarray(void *ptr, size_t nelem, size_t elsize, const char *file, int line)
{
	size_t newsize;

	if (GIT_MULTIPLY_SIZET_OVERFLOW(&newsize, nelem, elsize))
		return NULL;

	return stdalloc__realloc(ptr, newsize, file, line);
}

static void *stdalloc__mallocarray(size_t nelem, size_t elsize, const char *file, int line)
{
	return stdalloc__reallocarray(NULL, nelem, elsize, file, line);
}

static void stdalloc__free(void *ptr)
{
	free(ptr);
}

int git_stdalloc_init_allocator(git_allocator *allocator)
{
	allocator->gmalloc = stdalloc__malloc;
	allocator->gcalloc = stdalloc__calloc;
	allocator->gstrdup = stdalloc__strdup;
	allocator->gstrndup = stdalloc__strndup;
	allocator->gsubstrdup = stdalloc__substrdup;
	allocator->grealloc = stdalloc__realloc;
	allocator->greallocarray = stdalloc__reallocarray;
	allocator->gmallocarray = stdalloc__mallocarray;
	allocator->gfree = stdalloc__free;
	return 0;
}