beta-0.89.2
[luatex.git] / source / libs / poppler / poppler-src / goo / gmem.cc
blobc1c607ac3f36453b7ae6b34e138dca909b0038a9
1 /*
2 * gmem.c
4 * Memory routines with out-of-memory checking.
6 * Copyright 1996-2003 Glyph & Cog, LLC
7 */
9 //========================================================================
11 // Modified under the Poppler project - http://poppler.freedesktop.org
13 // All changes made under the Poppler project to this file are licensed
14 // under GPL version 2 or later
16 // Copyright (C) 2005 Takashi Iwai <tiwai@suse.de>
17 // Copyright (C) 2007-2010, 2012 Albert Astals Cid <aacid@kde.org>
18 // Copyright (C) 2008 Jonathan Kew <jonathan_kew@sil.org>
20 // To see a description of the changes please see the Changelog file that
21 // came with your tarball or type make ChangeLog if you are building from git
23 //========================================================================
25 #include <config.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <stddef.h>
29 #include <string.h>
30 #include <limits.h>
31 #include "gmem.h"
33 #ifdef DEBUG_MEM
35 typedef struct _GMemHdr {
36 unsigned int magic;
37 int size;
38 int index;
39 struct _GMemHdr *next, *prev;
40 } GMemHdr;
42 #define gMemHdrSize ((sizeof(GMemHdr) + 7) & ~7)
43 #define gMemTrlSize (sizeof(long))
45 #define gMemMagic 0xabcd9999
47 #if gmemTrlSize==8
48 #define gMemDeadVal 0xdeadbeefdeadbeefUL
49 #else
50 #define gMemDeadVal 0xdeadbeefUL
51 #endif
53 /* round data size so trailer will be aligned */
54 #define gMemDataSize(size) \
55 ((((size) + gMemTrlSize - 1) / gMemTrlSize) * gMemTrlSize)
57 static GMemHdr *gMemHead = NULL;
58 static GMemHdr *gMemTail = NULL;
60 static int gMemIndex = 0;
61 static int gMemAlloc = 0;
62 static int gMemInUse = 0;
64 #endif /* DEBUG_MEM */
66 inline static void *gmalloc(size_t size, bool checkoverflow) {
67 #ifdef DEBUG_MEM
68 int size1;
69 char *mem;
70 GMemHdr *hdr;
71 void *data;
72 unsigned long *trl, *p;
74 if (size == 0) {
75 return NULL;
77 size1 = gMemDataSize(size);
78 if (!(mem = (char *)malloc(size1 + gMemHdrSize + gMemTrlSize))) {
79 fprintf(stderr, "Out of memory\n");
80 if (checkoverflow) return NULL;
81 else exit(1);
83 hdr = (GMemHdr *)mem;
84 data = (void *)(mem + gMemHdrSize);
85 trl = (unsigned long *)(mem + gMemHdrSize + size1);
86 hdr->magic = gMemMagic;
87 hdr->size = size;
88 hdr->index = gMemIndex++;
89 if (gMemTail) {
90 gMemTail->next = hdr;
91 hdr->prev = gMemTail;
92 gMemTail = hdr;
93 } else {
94 hdr->prev = NULL;
95 gMemHead = gMemTail = hdr;
97 hdr->next = NULL;
98 ++gMemAlloc;
99 gMemInUse += size;
100 for (p = (unsigned long *)data; p <= trl; ++p) {
101 *p = gMemDeadVal;
103 return data;
104 #else
105 void *p;
107 if (size == 0) {
108 return NULL;
110 if (!(p = malloc(size))) {
111 fprintf(stderr, "Out of memory\n");
112 if (checkoverflow) return NULL;
113 else exit(1);
115 return p;
116 #endif
119 void *gmalloc(size_t size) {
120 return gmalloc(size, false);
123 void *gmalloc_checkoverflow(size_t size) {
124 return gmalloc(size, true);
127 inline static void *grealloc(void *p, size_t size, bool checkoverflow) {
128 #ifdef DEBUG_MEM
129 GMemHdr *hdr;
130 void *q;
131 int oldSize;
133 if (size == 0) {
134 if (p) {
135 gfree(p);
137 return NULL;
139 if (p) {
140 hdr = (GMemHdr *)((char *)p - gMemHdrSize);
141 oldSize = hdr->size;
142 q = gmalloc(size, checkoverflow);
143 memcpy(q, p, size < oldSize ? size : oldSize);
144 gfree(p);
145 } else {
146 q = gmalloc(size, checkoverflow);
148 return q;
149 #else
150 void *q;
152 if (size == 0) {
153 if (p) {
154 free(p);
156 return NULL;
158 if (p) {
159 q = realloc(p, size);
160 } else {
161 q = malloc(size);
163 if (!q) {
164 fprintf(stderr, "Out of memory\n");
165 if (checkoverflow) return NULL;
166 else exit(1);
168 return q;
169 #endif
172 void *grealloc(void *p, size_t size) {
173 return grealloc(p, size, false);
176 void *grealloc_checkoverflow(void *p, size_t size) {
177 return grealloc(p, size, true);
180 inline static void *gmallocn(int nObjs, int objSize, bool checkoverflow) {
181 int n;
183 if (nObjs == 0) {
184 return NULL;
186 n = nObjs * objSize;
187 if (objSize <= 0 || nObjs < 0 || nObjs >= INT_MAX / objSize) {
188 fprintf(stderr, "Bogus memory allocation size\n");
189 if (checkoverflow) return NULL;
190 else exit(1);
192 return gmalloc(n, checkoverflow);
195 void *gmallocn(int nObjs, int objSize) {
196 return gmallocn(nObjs, objSize, false);
199 void *gmallocn_checkoverflow(int nObjs, int objSize) {
200 return gmallocn(nObjs, objSize, true);
203 inline static void *gmallocn3(int a, int b, int c, bool checkoverflow) {
204 int n = a * b;
205 if (b <= 0 || a < 0 || a >= INT_MAX / b) {
206 fprintf(stderr, "Bogus memory allocation size\n");
207 if (checkoverflow) return NULL;
208 else exit(1);
210 return gmallocn(n, c, checkoverflow);
213 void *gmallocn3(int a, int b, int c) {
214 return gmallocn3(a, b, c, false);
217 void *gmallocn3_checkoverflow(int a, int b, int c) {
218 return gmallocn3(a, b, c, true);
221 inline static void *greallocn(void *p, int nObjs, int objSize, bool checkoverflow) {
222 int n;
224 if (nObjs == 0) {
225 if (p) {
226 gfree(p);
228 return NULL;
230 n = nObjs * objSize;
231 if (objSize <= 0 || nObjs < 0 || nObjs >= INT_MAX / objSize) {
232 fprintf(stderr, "Bogus memory allocation size\n");
233 if (checkoverflow) {
234 gfree(p);
235 return NULL;
236 } else {
237 exit(1);
240 return grealloc(p, n, checkoverflow);
243 void *greallocn(void *p, int nObjs, int objSize) {
244 return greallocn(p, nObjs, objSize, false);
247 void *greallocn_checkoverflow(void *p, int nObjs, int objSize) {
248 return greallocn(p, nObjs, objSize, true);
251 void gfree(void *p) {
252 #ifdef DEBUG_MEM
253 int size;
254 GMemHdr *hdr;
255 unsigned long *trl, *clr;
257 if (p) {
258 hdr = (GMemHdr *)((char *)p - gMemHdrSize);
259 if (hdr->magic == gMemMagic &&
260 ((hdr->prev == NULL) == (hdr == gMemHead)) &&
261 ((hdr->next == NULL) == (hdr == gMemTail))) {
262 if (hdr->prev) {
263 hdr->prev->next = hdr->next;
264 } else {
265 gMemHead = hdr->next;
267 if (hdr->next) {
268 hdr->next->prev = hdr->prev;
269 } else {
270 gMemTail = hdr->prev;
272 --gMemAlloc;
273 gMemInUse -= hdr->size;
274 size = gMemDataSize(hdr->size);
275 trl = (unsigned long *)((char *)hdr + gMemHdrSize + size);
276 if (*trl != gMemDeadVal) {
277 fprintf(stderr, "Overwrite past end of block %d at address %p\n",
278 hdr->index, p);
280 for (clr = (unsigned long *)hdr; clr <= trl; ++clr) {
281 *clr = gMemDeadVal;
283 free(hdr);
284 } else {
285 fprintf(stderr, "Attempted to free bad address %p\n", p);
288 #else
289 if (p) {
290 free(p);
292 #endif
295 #ifdef DEBUG_MEM
296 void gMemReport(FILE *f) {
297 GMemHdr *p;
299 fprintf(f, "%d memory allocations in all\n", gMemIndex);
300 if (gMemAlloc > 0) {
301 fprintf(f, "%d memory blocks left allocated:\n", gMemAlloc);
302 fprintf(f, " index size\n");
303 fprintf(f, "-------- --------\n");
304 for (p = gMemHead; p; p = p->next) {
305 fprintf(f, "%8d %8d\n", p->index, p->size);
307 } else {
308 fprintf(f, "No memory blocks left allocated\n");
311 #endif
313 char *copyString(const char *s) {
314 char *s1;
316 s1 = (char *)gmalloc(strlen(s) + 1);
317 strcpy(s1, s);
318 return s1;
321 char *gstrndup(const char *s, size_t n) {
322 char *s1 = (char*)gmalloc(n + 1); /* cannot return NULL for size > 0 */
323 s1[n] = '\0';
324 memcpy(s1, s, n);
325 return s1;