]> git.proxmox.com Git - libgit2.git/blame - src/pool.c
Merge pull request #3170 from CmdrMoozy/nsec_fix
[libgit2.git] / src / pool.c
CommitLineData
2bc8fa02 1#include "pool.h"
62e562f9 2#include "posix.h"
2bc8fa02
RB
3#ifndef GIT_WIN32
4#include <unistd.h>
5#endif
6
7struct git_pool_page {
8 git_pool_page *next;
9 uint32_t size;
10 uint32_t avail;
1e5e02b4 11 char data[GIT_FLEX_ARRAY];
2bc8fa02
RB
12};
13
1e5e02b4 14static void *pool_alloc_page(git_pool *pool, uint32_t size);
14bedad9 15
1e5e02b4
VM
16uint32_t git_pool__system_page_size(void)
17{
18 static uint32_t size = 0;
2bc8fa02 19
1e5e02b4
VM
20 if (!size) {
21 size_t page_size;
22 if (git__page_size(&page_size) < 0)
23 page_size = 4096;
410efda8
VM
24 /* allow space for malloc overhead */
25 size = page_size - (2 * sizeof(void *)) - sizeof(git_pool_page);
1e5e02b4 26 }
2bc8fa02 27
1e5e02b4
VM
28 return size;
29}
30
31void git_pool_init(git_pool *pool, uint32_t item_size)
2bc8fa02 32{
1e5e02b4 33 const uint32_t align_size = sizeof(void *) - 1;
2bc8fa02
RB
34 assert(pool);
35
1e5e02b4
VM
36 if (item_size > 1)
37 item_size = (item_size + align_size) & ~align_size;
2bc8fa02
RB
38
39 memset(pool, 0, sizeof(git_pool));
40 pool->item_size = item_size;
1e5e02b4 41 pool->page_size = git_pool__system_page_size();
2bc8fa02
RB
42}
43
44void git_pool_clear(git_pool *pool)
45{
46 git_pool_page *scan, *next;
47
1e5e02b4 48 for (scan = pool->pages; scan != NULL; scan = next) {
2bc8fa02
RB
49 next = scan->next;
50 git__free(scan);
51 }
2bc8fa02 52
1e5e02b4 53 pool->pages = NULL;
2bc8fa02
RB
54}
55
19fa2bc1
RB
56void git_pool_swap(git_pool *a, git_pool *b)
57{
58 git_pool temp;
59
60 if (a == b)
61 return;
62
63 memcpy(&temp, a, sizeof(temp));
64 memcpy(a, b, sizeof(temp));
65 memcpy(b, &temp, sizeof(temp));
66}
67
19fa2bc1 68static void *pool_alloc_page(git_pool *pool, uint32_t size)
2bc8fa02
RB
69{
70 git_pool_page *page;
1e5e02b4 71 const uint32_t new_page_size = (size <= pool->page_size) ? pool->page_size : size;
f1453c59 72 size_t alloc_size;
2bc8fa02 73
f1453c59 74 if (GIT_ADD_SIZET_OVERFLOW(&alloc_size, new_page_size, sizeof(git_pool_page)) ||
d3416dfe 75 !(page = git__malloc(alloc_size)))
19fa2bc1 76 return NULL;
2bc8fa02 77
1e5e02b4 78 page->size = new_page_size;
f1453c59 79 page->avail = new_page_size - size;
1e5e02b4 80 page->next = pool->pages;
2bc8fa02 81
1e5e02b4 82 pool->pages = page;
2bc8fa02 83
19fa2bc1 84 return page->data;
2bc8fa02
RB
85}
86
d3416dfe 87static void *pool_alloc(git_pool *pool, uint32_t size)
2bc8fa02 88{
1e5e02b4
VM
89 git_pool_page *page = pool->pages;
90 void *ptr = NULL;
2bc8fa02 91
1e5e02b4 92 if (!page || page->avail < size)
19fa2bc1
RB
93 return pool_alloc_page(pool, size);
94
1e5e02b4
VM
95 ptr = &page->data[page->size - page->avail];
96 page->avail -= size;
2bc8fa02 97
19fa2bc1 98 return ptr;
2bc8fa02
RB
99}
100
d3416dfe
VM
101void *git_pool_malloc(git_pool *pool, uint32_t items)
102{
103 const uint32_t size = items * pool->item_size;
104 return pool_alloc(pool, size);
105}
106
107void *git_pool_mallocz(git_pool *pool, uint32_t items)
108{
109 const uint32_t size = items * pool->item_size;
110 void *ptr = pool_alloc(pool, size);
111 if (ptr)
112 memset(ptr, 0x0, size);
113 return ptr;
114}
115
2bc8fa02
RB
116char *git_pool_strndup(git_pool *pool, const char *str, size_t n)
117{
ce33645f 118 char *ptr = NULL;
2bc8fa02
RB
119
120 assert(pool && str && pool->item_size == sizeof(char));
121
437f7d69
VM
122 if ((uint32_t)(n + 1) < n)
123 return NULL;
124
821f6bc7 125 if ((ptr = git_pool_malloc(pool, (uint32_t)(n + 1))) != NULL) {
2bc8fa02 126 memcpy(ptr, str, n);
ce33645f 127 ptr[n] = '\0';
19fa2bc1 128 }
ce33645f 129
2bc8fa02
RB
130 return ptr;
131}
132
133char *git_pool_strdup(git_pool *pool, const char *str)
134{
135 assert(pool && str && pool->item_size == sizeof(char));
19fa2bc1
RB
136 return git_pool_strndup(pool, str, strlen(str));
137}
138
71d27358
RB
139char *git_pool_strdup_safe(git_pool *pool, const char *str)
140{
ce33645f 141 return str ? git_pool_strdup(pool, str) : NULL;
71d27358
RB
142}
143
19fa2bc1
RB
144char *git_pool_strcat(git_pool *pool, const char *a, const char *b)
145{
146 void *ptr;
147 size_t len_a, len_b;
148
9ae4ad2d 149 assert(pool && pool->item_size == sizeof(char));
19fa2bc1
RB
150
151 len_a = a ? strlen(a) : 0;
152 len_b = b ? strlen(b) : 0;
153
821f6bc7 154 if ((ptr = git_pool_malloc(pool, (uint32_t)(len_a + len_b + 1))) != NULL) {
19fa2bc1
RB
155 if (len_a)
156 memcpy(ptr, a, len_a);
157 if (len_b)
158 memcpy(((char *)ptr) + len_a, b, len_b);
159 *(((char *)ptr) + len_a + len_b) = '\0';
160 }
19fa2bc1 161 return ptr;
2bc8fa02
RB
162}
163
2bc8fa02
RB
164uint32_t git_pool__open_pages(git_pool *pool)
165{
166 uint32_t ct = 0;
167 git_pool_page *scan;
1e5e02b4 168 for (scan = pool->pages; scan != NULL; scan = scan->next) ct++;
2bc8fa02
RB
169 return ct;
170}
171
172bool git_pool__ptr_in_pool(git_pool *pool, void *ptr)
173{
174 git_pool_page *scan;
1e5e02b4 175 for (scan = pool->pages; scan != NULL; scan = scan->next)
821f6bc7
RB
176 if ((void *)scan->data <= ptr &&
177 (void *)(((char *)scan->data) + scan->size) > ptr)
2bc8fa02
RB
178 return true;
179 return false;
180}