Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-11 10:26:10

0001 /*
0002  * gmem.h
0003  *
0004  * Memory routines with out-of-memory checking.
0005  *
0006  * Copyright 1996-2003 Glyph & Cog, LLC
0007  */
0008 
0009 //========================================================================
0010 //
0011 // Modified under the Poppler project - http://poppler.freedesktop.org
0012 //
0013 // All changes made under the Poppler project to this file are licensed
0014 // under GPL version 2 or later
0015 //
0016 // Copyright (C) 2005 Takashi Iwai <tiwai@suse.de>
0017 // Copyright (C) 2007-2010, 2017, 2019, 2022 Albert Astals Cid <aacid@kde.org>
0018 // Copyright (C) 2008 Jonathan Kew <jonathan_kew@sil.org>
0019 // Copyright (C) 2018 Adam Reichold <adam.reichold@t-online.de>
0020 // Copyright (C) 2021 Even Rouault <even.rouault@spatialys.com>
0021 //
0022 // To see a description of the changes please see the Changelog file that
0023 // came with your tarball or type make ChangeLog if you are building from git
0024 //
0025 //========================================================================
0026 
0027 #ifndef GMEM_H
0028 #define GMEM_H
0029 
0030 #include <cassert>
0031 #include <cstring>
0032 #include <cstdlib>
0033 #include <cstdio>
0034 
0035 #include "GooCheckedOps.h"
0036 
0037 /// Same as malloc, but prints error message and exits if malloc() returns NULL.
0038 inline void *gmalloc(size_t size, bool checkoverflow = false)
0039 {
0040     if (size == 0) {
0041         return nullptr;
0042     }
0043 
0044     if (void *p = std::malloc(size)) {
0045         return p;
0046     }
0047 
0048     std::fputs("Out of memory\n", stderr);
0049 
0050     if (checkoverflow) {
0051         return nullptr;
0052     }
0053 
0054     std::abort();
0055 }
0056 
0057 inline void *gmalloc_checkoverflow(size_t size)
0058 {
0059     return gmalloc(size, true);
0060 }
0061 
0062 /// Same as free
0063 inline void gfree(void *p)
0064 {
0065     std::free(p);
0066 }
0067 
0068 /// Same as realloc, but prints error message and exits if realloc() returns NULL.
0069 /// If <p> is NULL, calls malloc() instead of realloc().
0070 inline void *grealloc(void *p, size_t size, bool checkoverflow = false)
0071 {
0072     if (size == 0) {
0073         gfree(p);
0074         return nullptr;
0075     }
0076 
0077     if (void *q = p ? std::realloc(p, size) : std::malloc(size)) {
0078         return q;
0079     }
0080 
0081     std::fputs("Out of memory\n", stderr);
0082 
0083     if (checkoverflow) {
0084         return nullptr;
0085     }
0086 
0087     std::abort();
0088 }
0089 
0090 inline void *grealloc_checkoverflow(void *p, size_t size)
0091 {
0092     return grealloc(p, size, true);
0093 }
0094 
0095 /*
0096  * These are similar to gmalloc and grealloc, but take an object count
0097  * and size. The result is similar to allocating <count> * <size>
0098  * bytes, but there is an additional error check that the total size
0099  * doesn't overflow an int.
0100  * The gmallocn_checkoverflow variant returns NULL instead of exiting
0101  * the application if a overflow is detected.
0102  */
0103 
0104 inline void *gmallocn(int count, int size, bool checkoverflow = false)
0105 {
0106     if (count == 0) {
0107         return nullptr;
0108     }
0109 
0110     int bytes;
0111     if (count < 0 || size <= 0 || checkedMultiply(count, size, &bytes)) {
0112         std::fputs("Bogus memory allocation size\n", stderr);
0113 
0114         if (checkoverflow) {
0115             return nullptr;
0116         }
0117 
0118         std::abort();
0119     }
0120 
0121     return gmalloc(bytes, checkoverflow);
0122 }
0123 
0124 inline void *gmallocn_checkoverflow(int count, int size)
0125 {
0126     return gmallocn(count, size, true);
0127 }
0128 
0129 inline void *gmallocn3(int width, int height, int size, bool checkoverflow = false)
0130 {
0131     if (width == 0 || height == 0) {
0132         return nullptr;
0133     }
0134 
0135     int count;
0136     int bytes;
0137     if (width < 0 || height < 0 || size <= 0 || checkedMultiply(width, height, &count) || checkedMultiply(count, size, &bytes)) {
0138         std::fputs("Bogus memory allocation size\n", stderr);
0139 
0140         if (checkoverflow) {
0141             return nullptr;
0142         }
0143 
0144         std::abort();
0145     }
0146 
0147     return gmalloc(bytes, checkoverflow);
0148 }
0149 
0150 inline void *greallocn(void *p, int count, int size, bool checkoverflow = false, bool free_p = true)
0151 {
0152     if (count == 0) {
0153         if (free_p) {
0154             gfree(p);
0155         }
0156         return nullptr;
0157     }
0158 
0159     int bytes;
0160     if (count < 0 || size <= 0 || checkedMultiply(count, size, &bytes)) {
0161         std::fputs("Bogus memory allocation size\n", stderr);
0162 
0163         if (checkoverflow) {
0164             if (free_p) {
0165                 gfree(p);
0166             }
0167             return nullptr;
0168         }
0169 
0170         std::abort();
0171     }
0172 
0173     assert(bytes > 0);
0174     if (void *q = grealloc(p, bytes, checkoverflow)) {
0175         return q;
0176     }
0177     if (free_p) {
0178         gfree(p);
0179     }
0180     return nullptr;
0181 }
0182 
0183 inline void *greallocn_checkoverflow(void *p, int count, int size)
0184 {
0185     return greallocn(p, count, size, true);
0186 }
0187 
0188 /// Allocate memory and copy a string into it.
0189 inline char *copyString(const char *s)
0190 {
0191     char *r = static_cast<char *>(gmalloc(std::strlen(s) + 1, false));
0192     return std::strcpy(r, s);
0193 }
0194 
0195 /// Allocate memory and copy a limited-length string to it.
0196 inline char *copyString(const char *s, size_t n)
0197 {
0198     char *r = static_cast<char *>(gmalloc(n + 1, false));
0199     r[n] = '\0';
0200     return std::strncpy(r, s, n);
0201 }
0202 
0203 #endif // GMEM_H