source: trunk/poppler/mypoppler/goo/gmem.cc @ 470

Last change on this file since 470 was 470, checked in by Silvan Scherrer, 11 years ago

poppler, jpeg, freetype lib updates

File size: 7.0 KB
Line 
1/*
2 * gmem.c
3 *
4 * Memory routines with out-of-memory checking.
5 *
6 * Copyright 1996-2003 Glyph & Cog, LLC
7 */
8
9//========================================================================
10//
11// Modified under the Poppler project - http://poppler.freedesktop.org
12//
13// All changes made under the Poppler project to this file are licensed
14// under GPL version 2 or later
15//
16// Copyright (C) 2005 Takashi Iwai <tiwai@suse.de>
17// Copyright (C) 2007-2010 Albert Astals Cid <aacid@kde.org>
18// Copyright (C) 2008 Jonathan Kew <jonathan_kew@sil.org>
19//
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
22//
23//========================================================================
24
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"
32
33#ifdef DEBUG_MEM
34
35typedef struct _GMemHdr {
36  unsigned int magic;
37  int size;
38  int index;
39  struct _GMemHdr *next, *prev;
40} GMemHdr;
41
42#define gMemHdrSize ((sizeof(GMemHdr) + 7) & ~7)
43#define gMemTrlSize (sizeof(long))
44
45#define gMemMagic 0xabcd9999
46
47#if gmemTrlSize==8
48#define gMemDeadVal 0xdeadbeefdeadbeefUL
49#else
50#define gMemDeadVal 0xdeadbeefUL
51#endif
52
53/* round data size so trailer will be aligned */
54#define gMemDataSize(size) \
55  ((((size) + gMemTrlSize - 1) / gMemTrlSize) * gMemTrlSize)
56
57static GMemHdr *gMemHead = NULL;
58static GMemHdr *gMemTail = NULL;
59
60static int gMemIndex = 0;
61static int gMemAlloc = 0;
62static int gMemInUse = 0;
63
64#endif /* DEBUG_MEM */
65
66inline 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;
73
74  if (size <= 0) {
75    return NULL;
76  }
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);
82  }
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;
96  }
97  hdr->next = NULL;
98  ++gMemAlloc;
99  gMemInUse += size;
100  for (p = (unsigned long *)data; p <= trl; ++p) {
101    *p = gMemDeadVal;
102  }
103  return data;
104#else
105  void *p;
106
107  if (size <= 0) {
108    return NULL;
109  }
110  if (!(p = malloc(size))) {
111    fprintf(stderr, "Out of memory\n");
112    if (checkoverflow) return NULL;
113    else exit(1);
114  }
115  return p;
116#endif
117}
118
119void *gmalloc(size_t size) {
120  return gmalloc(size, false);
121}
122
123void *gmalloc_checkoverflow(size_t size) {
124  return gmalloc(size, true);
125}
126
127inline static void *grealloc(void *p, size_t size, bool checkoverflow) {
128#ifdef DEBUG_MEM
129  GMemHdr *hdr;
130  void *q;
131  int oldSize;
132
133  if (size <= 0) {
134    if (p) {
135      gfree(p);
136    }
137    return NULL;
138  }
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);
147  }
148  return q;
149#else
150  void *q;
151
152  if (size <= 0) {
153    if (p) {
154      free(p);
155    }
156    return NULL;
157  }
158  if (p) {
159    q = realloc(p, size);
160  } else {
161    q = malloc(size);
162  }
163  if (!q) {
164    fprintf(stderr, "Out of memory\n");
165    if (checkoverflow) return NULL;
166    else exit(1);
167  }
168  return q;
169#endif
170}
171
172void *grealloc(void *p, size_t size) {
173  return grealloc(p, size, false);
174}
175
176void *grealloc_checkoverflow(void *p, size_t size) {
177  return grealloc(p, size, true);
178}
179
180inline static void *gmallocn(int nObjs, int objSize, bool checkoverflow) {
181  int n;
182
183  if (nObjs == 0) {
184    return NULL;
185  }
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);
191  }
192  return gmalloc(n, checkoverflow);
193}
194
195void *gmallocn(int nObjs, int objSize) {
196  return gmallocn(nObjs, objSize, false);
197}
198
199void *gmallocn_checkoverflow(int nObjs, int objSize) {
200  return gmallocn(nObjs, objSize, true);
201}
202
203inline 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);
209  }
210  return gmallocn(n, c, checkoverflow);
211}
212
213void *gmallocn3(int a, int b, int c) {
214  return gmallocn3(a, b, c, false);
215}
216
217void *gmallocn3_checkoverflow(int a, int b, int c) {
218  return gmallocn3(a, b, c, true);
219}
220
221inline static void *greallocn(void *p, int nObjs, int objSize, bool checkoverflow) {
222  int n;
223
224  if (nObjs == 0) {
225    if (p) {
226      gfree(p);
227    }
228    return NULL;
229  }
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);
238    }
239  }
240  return grealloc(p, n, checkoverflow);
241}
242
243void *greallocn(void *p, int nObjs, int objSize) {
244  return greallocn(p, nObjs, objSize, false);
245}
246
247void *greallocn_checkoverflow(void *p, int nObjs, int objSize) {
248  return greallocn(p, nObjs, objSize, true);
249}
250
251void gfree(void *p) {
252#ifdef DEBUG_MEM
253  int size;
254  GMemHdr *hdr;
255  unsigned long *trl, *clr;
256
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;
266      }
267      if (hdr->next) {
268        hdr->next->prev = hdr->prev;
269      } else {
270        gMemTail = hdr->prev;
271      }
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);
279      }
280      for (clr = (unsigned long *)hdr; clr <= trl; ++clr) {
281        *clr = gMemDeadVal;
282      }
283      free(hdr);
284    } else {
285      fprintf(stderr, "Attempted to free bad address %p\n", p);
286    }
287  }
288#else
289  if (p) {
290    free(p);
291  }
292#endif
293}
294
295#ifdef DEBUG_MEM
296void gMemReport(FILE *f) {
297  GMemHdr *p;
298
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);
306    }
307  } else {
308    fprintf(f, "No memory blocks left allocated\n");
309  }
310}
311#endif
312
313char *copyString(char *s) {
314  char *s1;
315
316  s1 = (char *)gmalloc(strlen(s) + 1);
317  strcpy(s1, s);
318  return s1;
319}
320
321char *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;
326}
Note: See TracBrowser for help on using the repository browser.