Coverage Report

Created: 2026-07-30 07:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/poppler/goo/gmem.h
Line
Count
Source
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, 2025 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.
38
inline void *gmalloc(size_t size, bool checkoverflow = false)
39
917k
{
40
917k
    if (size == 0) {
41
0
        return nullptr;
42
0
    }
43
44
917k
    if (void *p = std::malloc(size)) {
45
917k
        return p;
46
917k
    }
47
48
0
    std::fputs("Out of memory\n", stderr);
49
50
0
    if (checkoverflow) {
51
0
        return nullptr;
52
0
    }
53
54
0
    std::abort();
55
0
}
56
57
inline void *gmalloc_checkoverflow(size_t size)
58
0
{
59
0
    return gmalloc(size, true);
60
0
}
61
62
/// Same as free
63
inline void gfree(void *p)
64
1.08M
{
65
1.08M
    std::free(p);
66
1.08M
}
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().
70
inline void *grealloc(void *p, size_t size, bool checkoverflow = false)
71
47.8k
{
72
47.8k
    if (size == 0) {
73
0
        gfree(p);
74
0
        return nullptr;
75
0
    }
76
77
47.8k
    if (void *q = p ? std::realloc(p, size) : std::malloc(size)) {
78
47.8k
        return q;
79
47.8k
    }
80
81
0
    std::fputs("Out of memory\n", stderr);
82
83
0
    if (checkoverflow) {
84
0
        return nullptr;
85
0
    }
86
87
0
    std::abort();
88
0
}
89
90
/*
91
 * These are similar to gmalloc and grealloc, but take an object count
92
 * and size. The result is similar to allocating <count> * <size>
93
 * bytes, but there is an additional error check that the total size
94
 * doesn't overflow an int.
95
 * The gmallocn_checkoverflow variant returns NULL instead of exiting
96
 * the application if a overflow is detected.
97
 */
98
99
inline void *gmallocn(int count, int size, bool checkoverflow = false)
100
916k
{
101
916k
    if (count == 0) {
102
2.70k
        return nullptr;
103
2.70k
    }
104
105
913k
    int bytes;
106
913k
    if (count < 0 || size <= 0 || checkedMultiply(count, size, &bytes)) {
107
0
        std::fputs("Bogus memory allocation size\n", stderr);
108
109
0
        if (checkoverflow) {
110
0
            return nullptr;
111
0
        }
112
113
0
        std::abort();
114
0
    }
115
116
913k
    return gmalloc(bytes, checkoverflow);
117
913k
}
118
119
inline void *gmallocn_checkoverflow(int count, int size)
120
2.01k
{
121
2.01k
    return gmallocn(count, size, true);
122
2.01k
}
123
124
inline void *gmallocn3(int width, int height, int size, bool checkoverflow = false)
125
0
{
126
0
    if (width == 0 || height == 0) {
127
0
        return nullptr;
128
0
    }
129
0
130
0
    int count;
131
0
    int bytes;
132
0
    if (width < 0 || height < 0 || size <= 0 || checkedMultiply(width, height, &count) || checkedMultiply(count, size, &bytes)) {
133
0
        std::fputs("Bogus memory allocation size\n", stderr);
134
0
135
0
        if (checkoverflow) {
136
0
            return nullptr;
137
0
        }
138
0
139
0
        std::abort();
140
0
    }
141
0
142
0
    return gmalloc(bytes, checkoverflow);
143
0
}
144
145
inline void *greallocn(void *p, int count, int size, bool checkoverflow = false)
146
27.0k
{
147
27.0k
    if (count == 0) {
148
0
        gfree(p);
149
0
        return nullptr;
150
0
    }
151
152
27.0k
    int bytes;
153
27.0k
    if (count < 0 || size <= 0 || checkedMultiply(count, size, &bytes)) {
154
0
        std::fputs("Bogus memory allocation size\n", stderr);
155
156
0
        if (checkoverflow) {
157
0
            gfree(p);
158
0
            return nullptr;
159
0
        }
160
161
0
        std::abort();
162
0
    }
163
164
27.0k
    assert(bytes > 0);
165
27.0k
    if (void *q = grealloc(p, bytes, checkoverflow)) {
166
27.0k
        return q;
167
27.0k
    }
168
0
    gfree(p);
169
0
    return nullptr;
170
27.0k
}
171
172
inline void *greallocn_checkoverflow(void *p, int count, int size)
173
0
{
174
0
    return greallocn(p, count, size, true);
175
0
}
176
177
/// Allocate memory and copy a string into it.
178
inline char *copyString(const char *s)
179
0
{
180
0
    char *r = static_cast<char *>(gmalloc(std::strlen(s) + 1, false));
181
0
    return std::strcpy(r, s);
182
0
}
183
184
/// Allocate memory and copy a limited-length string to it.
185
inline char *copyString(const char *s, size_t n)
186
0
{
187
0
    char *r = static_cast<char *>(gmalloc(n + 1, false));
188
0
    r[n] = '\0';
189
0
    return std::strncpy(r, s, n);
190
0
}
191
192
#endif // GMEM_H