/* * gmem.h * * Memory routines with out-of-memory checking. * * Copyright 1996-2003 Glyph & Cog, LLC */ //======================================================================== // // Modified under the Poppler project - http://poppler.freedesktop.org // // All changes made under the Poppler project to this file are licensed // under GPL version 2 or later // // Copyright (C) 2005 Takashi Iwai // Copyright (C) 2007-2010, 2017, 2019, 2022 Albert Astals Cid // Copyright (C) 2008 Jonathan Kew // Copyright (C) 2018 Adam Reichold // Copyright (C) 2021 Even Rouault // // To see a description of the changes please see the Changelog file that // came with your tarball or type make ChangeLog if you are building from git // //======================================================================== #ifndef GMEM_H #define GMEM_H #include #include #include #include #include "GooCheckedOps.h" /// Same as malloc, but prints error message and exits if malloc() returns NULL. inline void *gmalloc(size_t size, bool checkoverflow = false) { if (size == 0) { return nullptr; } if (void *p = std::malloc(size)) { return p; } std::fputs("Out of memory\n", stderr); if (checkoverflow) { return nullptr; } std::abort(); } inline void *gmalloc_checkoverflow(size_t size) { return gmalloc(size, true); } /// Same as free inline void gfree(void *p) { std::free(p); } /// Same as realloc, but prints error message and exits if realloc() returns NULL. /// If

is NULL, calls malloc() instead of realloc(). inline void *grealloc(void *p, size_t size, bool checkoverflow = false) { if (size == 0) { gfree(p); return nullptr; } if (void *q = p ? std::realloc(p, size) : std::malloc(size)) { return q; } std::fputs("Out of memory\n", stderr); if (checkoverflow) { return nullptr; } std::abort(); } inline void *grealloc_checkoverflow(void *p, size_t size) { return grealloc(p, size, true); } /* * These are similar to gmalloc and grealloc, but take an object count * and size. The result is similar to allocating * * bytes, but there is an additional error check that the total size * doesn't overflow an int. * The gmallocn_checkoverflow variant returns NULL instead of exiting * the application if a overflow is detected. */ inline void *gmallocn(int count, int size, bool checkoverflow = false) { if (count == 0) { return nullptr; } int bytes; if (count < 0 || size <= 0 || checkedMultiply(count, size, &bytes)) { std::fputs("Bogus memory allocation size\n", stderr); if (checkoverflow) { return nullptr; } std::abort(); } return gmalloc(bytes, checkoverflow); } inline void *gmallocn_checkoverflow(int count, int size) { return gmallocn(count, size, true); } inline void *gmallocn3(int width, int height, int size, bool checkoverflow = false) { if (width == 0 || height == 0) { return nullptr; } int count; int bytes; if (width < 0 || height < 0 || size <= 0 || checkedMultiply(width, height, &count) || checkedMultiply(count, size, &bytes)) { std::fputs("Bogus memory allocation size\n", stderr); if (checkoverflow) { return nullptr; } std::abort(); } return gmalloc(bytes, checkoverflow); } inline void *greallocn(void *p, int count, int size, bool checkoverflow = false, bool free_p = true) { if (count == 0) { if (free_p) { gfree(p); } return nullptr; } int bytes; if (count < 0 || size <= 0 || checkedMultiply(count, size, &bytes)) { std::fputs("Bogus memory allocation size\n", stderr); if (checkoverflow) { if (free_p) { gfree(p); } return nullptr; } std::abort(); } assert(bytes > 0); if (void *q = grealloc(p, bytes, checkoverflow)) { return q; } if (free_p) { gfree(p); } return nullptr; } inline void *greallocn_checkoverflow(void *p, int count, int size) { return greallocn(p, count, size, true); } /// Allocate memory and copy a string into it. inline char *copyString(const char *s) { char *r = static_cast(gmalloc(std::strlen(s) + 1, false)); return std::strcpy(r, s); } /// Allocate memory and copy a limited-length string to it. inline char *copyString(const char *s, size_t n) { char *r = static_cast(gmalloc(n + 1, false)); r[n] = '\0'; return std::strncpy(r, s, n); } #endif // GMEM_H