PostgreSQL Source Code git master
Loading...
Searching...
No Matches
fe_memutils.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * fe_memutils.c
4 * memory management support for frontend code
5 *
6 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/common/fe_memutils.c
12 *
13 *-------------------------------------------------------------------------
14 */
15
16#ifndef FRONTEND
17#error "This file is not expected to be compiled for backend code"
18#endif
19
20#include "postgres_fe.h"
21
22#include "common/int.h"
23
26
27
28static inline void *
29pg_malloc_internal(size_t size, int flags)
30{
31 void *tmp;
32
33 /* Avoid unportable behavior of malloc(0) */
34 if (size == 0)
35 size = 1;
36 tmp = malloc(size);
37 if (tmp == NULL)
38 {
39 if ((flags & MCXT_ALLOC_NO_OOM) == 0)
40 {
41 fprintf(stderr, _("out of memory\n"));
43 }
44 return NULL;
45 }
46
47 if ((flags & MCXT_ALLOC_ZERO) != 0)
48 MemSet(tmp, 0, size);
49 return tmp;
50}
51
52void *
53pg_malloc(size_t size)
54{
55 return pg_malloc_internal(size, 0);
56}
57
58void *
59pg_malloc0(size_t size)
60{
62}
63
64void *
65pg_malloc_extended(size_t size, int flags)
66{
67 return pg_malloc_internal(size, flags);
68}
69
70void *
71pg_realloc(void *ptr, size_t size)
72{
73 void *tmp;
74
75 /* Avoid unportable behavior of realloc(NULL, 0) */
76 if (ptr == NULL && size == 0)
77 size = 1;
78 tmp = realloc(ptr, size);
79 if (!tmp)
80 {
81 fprintf(stderr, _("out of memory\n"));
83 }
84 return tmp;
85}
86
87/*
88 * "Safe" wrapper around strdup().
89 */
90char *
91pg_strdup(const char *in)
92{
93 char *tmp;
94
95 if (!in)
96 {
98 _("cannot duplicate null pointer (internal error)\n"));
100 }
101 tmp = strdup(in);
102 if (!tmp)
103 {
104 fprintf(stderr, _("out of memory\n"));
106 }
107 return tmp;
108}
109
110void
111pg_free(void *ptr)
112{
113 free(ptr);
114}
115
116/*
117 * Frontend emulation of backend memory management functions. Useful for
118 * programs that compile backend files.
119 */
120void *
122{
123 return pg_malloc_internal(size, 0);
124}
125
126void *
128{
130}
131
132void *
133palloc_extended(Size size, int flags)
134{
135 return pg_malloc_internal(size, flags);
136}
137
138void
139pfree(void *pointer)
140{
141 pg_free(pointer);
142}
143
144char *
145pstrdup(const char *in)
146{
147 return pg_strdup(in);
148}
149
150char *
151pnstrdup(const char *in, Size size)
152{
153 char *tmp;
154 int len;
155
156 if (!in)
157 {
159 _("cannot duplicate null pointer (internal error)\n"));
161 }
162
163 len = strnlen(in, size);
164 tmp = malloc(len + 1);
165 if (tmp == NULL)
166 {
167 fprintf(stderr, _("out of memory\n"));
169 }
170
171 memcpy(tmp, in, len);
172 tmp[len] = '\0';
173
174 return tmp;
175}
176
177void *
178repalloc(void *pointer, Size size)
179{
180 return pg_realloc(pointer, size);
181}
182
183/*
184 * Support for safe calculation of memory request sizes
185 *
186 * These functions perform the requested calculation, but throw error if the
187 * result overflows.
188 *
189 * An important property of these functions is that if an argument was a
190 * negative signed int before promotion (implying overflow in calculating it)
191 * we will detect that as an error. That happens because we reject results
192 * larger than SIZE_MAX / 2. In the backend we rely on later checks to do
193 * that, but in frontend we must do it here.
194 */
195Size
197{
198 Size result;
199
201 result > (SIZE_MAX / 2)))
203 return result;
204}
205
206pg_noreturn static pg_noinline void
208{
209 fprintf(stderr, _("invalid memory allocation request size %zu + %zu\n"),
210 s1, s2);
212}
213
214Size
216{
217 Size result;
218
220 result > (SIZE_MAX / 2)))
222 return result;
223}
224
225pg_noreturn static pg_noinline void
227{
228 fprintf(stderr, _("invalid memory allocation request size %zu * %zu\n"),
229 s1, s2);
231}
232
233/*
234 * pg_malloc_mul
235 * Equivalent to pg_malloc(mul_size(s1, s2)).
236 */
237void *
239{
240 /* inline mul_size() for efficiency */
241 Size req;
242
244 req > (SIZE_MAX / 2)))
246 return pg_malloc(req);
247}
248
249/*
250 * pg_malloc0_mul
251 * Equivalent to pg_malloc0(mul_size(s1, s2)).
252 *
253 * This is comparable to standard calloc's behavior.
254 */
255void *
257{
258 /* inline mul_size() for efficiency */
259 Size req;
260
262 req > (SIZE_MAX / 2)))
264 return pg_malloc0(req);
265}
266
267/*
268 * pg_malloc_mul_extended
269 * Equivalent to pg_malloc_extended(mul_size(s1, s2), flags).
270 */
271void *
273{
274 /* inline mul_size() for efficiency */
275 Size req;
276
278 req > (SIZE_MAX / 2)))
280 return pg_malloc_extended(req, flags);
281}
282
283/*
284 * pg_realloc_mul
285 * Equivalent to pg_realloc(p, mul_size(s1, s2)).
286 */
287void *
289{
290 /* inline mul_size() for efficiency */
291 Size req;
292
294 req > (SIZE_MAX / 2)))
296 return pg_realloc(p, req);
297}
298
299/*
300 * palloc_mul
301 * Equivalent to palloc(mul_size(s1, s2)).
302 */
303void *
305{
306 /* inline mul_size() for efficiency */
307 Size req;
308
310 req > (SIZE_MAX / 2)))
312 return palloc(req);
313}
314
315/*
316 * palloc0_mul
317 * Equivalent to palloc0(mul_size(s1, s2)).
318 *
319 * This is comparable to standard calloc's behavior.
320 */
321void *
323{
324 /* inline mul_size() for efficiency */
325 Size req;
326
328 req > (SIZE_MAX / 2)))
330 return palloc0(req);
331}
332
333/*
334 * palloc_mul_extended
335 * Equivalent to palloc_extended(mul_size(s1, s2), flags).
336 */
337void *
339{
340 /* inline mul_size() for efficiency */
341 Size req;
342
344 req > (SIZE_MAX / 2)))
346 return palloc_extended(req, flags);
347}
348
349/*
350 * repalloc_mul
351 * Equivalent to repalloc(p, mul_size(s1, s2)).
352 */
353void *
355{
356 /* inline mul_size() for efficiency */
357 Size req;
358
360 req > (SIZE_MAX / 2)))
362 return repalloc(p, req);
363}
#define pg_noinline
Definition c.h:321
#define pg_noreturn
Definition c.h:190
#define unlikely(x)
Definition c.h:438
#define MemSet(start, val, len)
Definition c.h:1107
size_t Size
Definition c.h:689
uint32 result
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
#define fprintf(file, fmt, msg)
Definition cubescan.l:21
#define _(x)
Definition elog.c:96
void * pg_malloc_mul_extended(Size s1, Size s2, int flags)
void * palloc_mul_extended(Size s1, Size s2, int flags)
Size add_size(Size s1, Size s2)
char * pstrdup(const char *in)
void * repalloc(void *pointer, Size size)
void pfree(void *pointer)
void * palloc0(Size size)
void * pg_malloc(size_t size)
Definition fe_memutils.c:53
Size mul_size(Size s1, Size s2)
static pg_noreturn pg_noinline void mul_size_error(Size s1, Size s2)
void * palloc(Size size)
static void * pg_malloc_internal(size_t size, int flags)
Definition fe_memutils.c:29
void * palloc0_mul(Size s1, Size s2)
void * palloc_extended(Size size, int flags)
void * pg_malloc_extended(size_t size, int flags)
Definition fe_memutils.c:65
void * palloc_mul(Size s1, Size s2)
char * pg_strdup(const char *in)
Definition fe_memutils.c:91
void * pg_malloc0_mul(Size s1, Size s2)
void * repalloc_mul(void *p, Size s1, Size s2)
void * pg_realloc_mul(void *p, Size s1, Size s2)
void * pg_malloc0(size_t size)
Definition fe_memutils.c:59
static pg_noreturn pg_noinline void add_size_error(Size s1, Size s2)
void pg_free(void *ptr)
void * pg_malloc_mul(Size s1, Size s2)
char * pnstrdup(const char *in, Size size)
void * pg_realloc(void *ptr, size_t size)
Definition fe_memutils.c:71
#define MCXT_ALLOC_ZERO
Definition fe_memutils.h:30
#define MCXT_ALLOC_NO_OOM
Definition fe_memutils.h:29
static bool pg_mul_size_overflow(size_t a, size_t b, size_t *result)
Definition int.h:642
static bool pg_add_size_overflow(size_t a, size_t b, size_t *result)
Definition int.h:608
const void size_t len
static int fb(int x)
char * s1
char * s2
#define EXIT_FAILURE
Definition settings.h:197
#define realloc(a, b)
#define free(a)
#define malloc(a)