4 * Memory routines with out-of-memory checking.
6 * Copyright 1996-2003 Glyph & Cog, LLC
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 //========================================================================
35 typedef struct _GMemHdr
{
39 struct _GMemHdr
*next
, *prev
;
42 #define gMemHdrSize ((sizeof(GMemHdr) + 7) & ~7)
43 #define gMemTrlSize (sizeof(long))
45 #define gMemMagic 0xabcd9999
48 #define gMemDeadVal 0xdeadbeefdeadbeefUL
50 #define gMemDeadVal 0xdeadbeefUL
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
) {
72 unsigned long *trl
, *p
;
77 size1
= gMemDataSize(size
);
78 if (!(mem
= (char *)malloc(size1
+ gMemHdrSize
+ gMemTrlSize
))) {
79 fprintf(stderr
, "Out of memory\n");
80 if (checkoverflow
) return NULL
;
84 data
= (void *)(mem
+ gMemHdrSize
);
85 trl
= (unsigned long *)(mem
+ gMemHdrSize
+ size1
);
86 hdr
->magic
= gMemMagic
;
88 hdr
->index
= gMemIndex
++;
95 gMemHead
= gMemTail
= hdr
;
100 for (p
= (unsigned long *)data
; p
<= trl
; ++p
) {
110 if (!(p
= malloc(size
))) {
111 fprintf(stderr
, "Out of memory\n");
112 if (checkoverflow
) return NULL
;
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
) {
140 hdr
= (GMemHdr
*)((char *)p
- gMemHdrSize
);
142 q
= gmalloc(size
, checkoverflow
);
143 memcpy(q
, p
, size
< oldSize
? size
: oldSize
);
146 q
= gmalloc(size
, checkoverflow
);
159 q
= realloc(p
, size
);
164 fprintf(stderr
, "Out of memory\n");
165 if (checkoverflow
) return NULL
;
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
) {
187 if (objSize
<= 0 || nObjs
< 0 || nObjs
>= INT_MAX
/ objSize
) {
188 fprintf(stderr
, "Bogus memory allocation size\n");
189 if (checkoverflow
) return NULL
;
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
) {
205 if (b
<= 0 || a
< 0 || a
>= INT_MAX
/ b
) {
206 fprintf(stderr
, "Bogus memory allocation size\n");
207 if (checkoverflow
) return NULL
;
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
) {
231 if (objSize
<= 0 || nObjs
< 0 || nObjs
>= INT_MAX
/ objSize
) {
232 fprintf(stderr
, "Bogus memory allocation size\n");
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
) {
255 unsigned long *trl
, *clr
;
258 hdr
= (GMemHdr
*)((char *)p
- gMemHdrSize
);
259 if (hdr
->magic
== gMemMagic
&&
260 ((hdr
->prev
== NULL
) == (hdr
== gMemHead
)) &&
261 ((hdr
->next
== NULL
) == (hdr
== gMemTail
))) {
263 hdr
->prev
->next
= hdr
->next
;
265 gMemHead
= hdr
->next
;
268 hdr
->next
->prev
= hdr
->prev
;
270 gMemTail
= hdr
->prev
;
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",
280 for (clr
= (unsigned long *)hdr
; clr
<= trl
; ++clr
) {
285 fprintf(stderr
, "Attempted to free bad address %p\n", p
);
296 void gMemReport(FILE *f
) {
299 fprintf(f
, "%d memory allocations in all\n", gMemIndex
);
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
);
308 fprintf(f
, "No memory blocks left allocated\n");
313 char *copyString(const char *s
) {
316 s1
= (char *)gmalloc(strlen(s
) + 1);
321 char *gstrndup(const char *s
, size_t n
) {
322 char *s1
= (char*)gmalloc(n
+ 1); /* cannot return NULL for size > 0 */