1/*
2 * gmem.h
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, 2017, 2019, 2022 Albert Astals Cid <aacid@kde.org>
18// Copyright (C) 2008 Jonathan Kew <jonathan_kew@sil.org>
19// Copyright (C) 2018 Adam Reichold <adam.reichold@t-online.de>
20// Copyright (C) 2021 Even Rouault <even.rouault@spatialys.com>
21//
22// To see a description of the changes please see the Changelog file that
23// came with your tarball or type make ChangeLog if you are building from git
24//
25//========================================================================
26
27#ifndef GMEM_H
28#define GMEM_H
29
30#include <cassert>
31#include <cstring>
32#include <cstdlib>
33#include <cstdio>
34
35#include "GooCheckedOps.h"
36
37/// Same as malloc, but prints error message and exits if malloc() returns NULL.
38inline void *gmalloc(size_t size, bool checkoverflow = false)
39{
40 if (size == 0) {
41 return nullptr;
42 }
43
44 if (void *p = std::malloc(size: size)) {
45 return p;
46 }
47
48 std::fputs(s: "Out of memory\n", stderr);
49
50 if (checkoverflow) {
51 return nullptr;
52 }
53
54 std::abort();
55}
56
57inline void *gmalloc_checkoverflow(size_t size)
58{
59 return gmalloc(size, checkoverflow: true);
60}
61
62/// Same as free
63inline void gfree(void *p)
64{
65 std::free(ptr: p);
66}
67
68/// Same as realloc, but prints error message and exits if realloc() returns NULL.
69/// If <p> is NULL, calls malloc() instead of realloc().
70inline void *grealloc(void *p, size_t size, bool checkoverflow = false)
71{
72 if (size == 0) {
73 gfree(p);
74 return nullptr;
75 }
76
77 if (void *q = p ? std::realloc(ptr: p, size: size) : std::malloc(size: size)) {
78 return q;
79 }
80
81 std::fputs(s: "Out of memory\n", stderr);
82
83 if (checkoverflow) {
84 return nullptr;
85 }
86
87 std::abort();
88}
89
90inline void *grealloc_checkoverflow(void *p, size_t size)
91{
92 return grealloc(p, size, checkoverflow: true);
93}
94
95/*
96 * These are similar to gmalloc and grealloc, but take an object count
97 * and size. The result is similar to allocating <count> * <size>
98 * bytes, but there is an additional error check that the total size
99 * doesn't overflow an int.
100 * The gmallocn_checkoverflow variant returns NULL instead of exiting
101 * the application if a overflow is detected.
102 */
103
104inline void *gmallocn(int count, int size, bool checkoverflow = false)
105{
106 if (count == 0) {
107 return nullptr;
108 }
109
110 int bytes;
111 if (count < 0 || size <= 0 || checkedMultiply(x: count, y: size, z: &bytes)) {
112 std::fputs(s: "Bogus memory allocation size\n", stderr);
113
114 if (checkoverflow) {
115 return nullptr;
116 }
117
118 std::abort();
119 }
120
121 return gmalloc(size: bytes, checkoverflow);
122}
123
124inline void *gmallocn_checkoverflow(int count, int size)
125{
126 return gmallocn(count, size, checkoverflow: true);
127}
128
129inline void *gmallocn3(int width, int height, int size, bool checkoverflow = false)
130{
131 if (width == 0 || height == 0) {
132 return nullptr;
133 }
134
135 int count;
136 int bytes;
137 if (width < 0 || height < 0 || size <= 0 || checkedMultiply(x: width, y: height, z: &count) || checkedMultiply(x: count, y: size, z: &bytes)) {
138 std::fputs(s: "Bogus memory allocation size\n", stderr);
139
140 if (checkoverflow) {
141 return nullptr;
142 }
143
144 std::abort();
145 }
146
147 return gmalloc(size: bytes, checkoverflow);
148}
149
150inline void *greallocn(void *p, int count, int size, bool checkoverflow = false, bool free_p = true)
151{
152 if (count == 0) {
153 if (free_p) {
154 gfree(p);
155 }
156 return nullptr;
157 }
158
159 int bytes;
160 if (count < 0 || size <= 0 || checkedMultiply(x: count, y: size, z: &bytes)) {
161 std::fputs(s: "Bogus memory allocation size\n", stderr);
162
163 if (checkoverflow) {
164 if (free_p) {
165 gfree(p);
166 }
167 return nullptr;
168 }
169
170 std::abort();
171 }
172
173 assert(bytes > 0);
174 if (void *q = grealloc(p, size: bytes, checkoverflow)) {
175 return q;
176 }
177 if (free_p) {
178 gfree(p);
179 }
180 return nullptr;
181}
182
183inline void *greallocn_checkoverflow(void *p, int count, int size)
184{
185 return greallocn(p, count, size, checkoverflow: true);
186}
187
188/// Allocate memory and copy a string into it.
189inline char *copyString(const char *s)
190{
191 char *r = static_cast<char *>(gmalloc(size: std::strlen(s: s) + 1, checkoverflow: false));
192 return std::strcpy(dest: r, src: s);
193}
194
195/// Allocate memory and copy a limited-length string to it.
196inline char *copyString(const char *s, size_t n)
197{
198 char *r = static_cast<char *>(gmalloc(size: n + 1, checkoverflow: false));
199 r[n] = '\0';
200 return std::strncpy(dest: r, src: s, n: n);
201}
202
203#endif // GMEM_H
204

source code of poppler/goo/gmem.h