Skip to content

Commit 09ac603

Browse files
committed
Work around unportable behavior of malloc(0) and realloc(NULL, 0).
On some platforms these functions return NULL, rather than the more common practice of returning a pointer to a zero-sized block of memory. Hack our various wrapper functions to hide the difference by substituting a size request of 1. This is probably not so important for the callers, who should never touch the block anyway if they asked for size 0 --- but it's important for the wrapper functions themselves, which mistakenly treated the NULL result as an out-of-memory failure. This broke at least pg_dump for the case of no user-defined aggregates, as per report from Matthew Carrington. Back-patch to 9.2 to fix the pg_dump issue. Given the lack of previous complaints, it seems likely that there is no live bug in previous releases, even though some of these functions were in place before that.
1 parent 2164f9a commit 09ac603

File tree

11 files changed

+85
-22
lines changed

11 files changed

+85
-22
lines changed

contrib/oid2name/oid2name.c

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ struct options
5151
static void help(const char *progname);
5252
void get_opts(int, char **, struct options *);
5353
void *pg_malloc(size_t size);
54+
void *pg_realloc(void *ptr, size_t size);
5455
char *pg_strdup(const char *str);
5556
void add_one_elt(char *eltname, eary *eary);
5657
char *get_comma_elts(eary *eary);
@@ -203,24 +204,45 @@ help(const char *progname)
203204
void *
204205
pg_malloc(size_t size)
205206
{
206-
void *ptr = malloc(size);
207+
void *ptr;
207208

209+
/* Avoid unportable behavior of malloc(0) */
210+
if (size == 0)
211+
size = 1;
212+
ptr = malloc(size);
208213
if (!ptr)
209214
{
210-
fprintf(stderr, "out of memory");
215+
fprintf(stderr, "out of memory\n");
211216
exit(1);
212217
}
213218
return ptr;
214219
}
215220

221+
void *
222+
pg_realloc(void *ptr, size_t size)
223+
{
224+
void *result;
225+
226+
/* Avoid unportable behavior of realloc(NULL, 0) */
227+
if (ptr == NULL && size == 0)
228+
size = 1;
229+
result = realloc(ptr, size);
230+
if (!result)
231+
{
232+
fprintf(stderr, "out of memory\n");
233+
exit(1);
234+
}
235+
return result;
236+
}
237+
216238
char *
217239
pg_strdup(const char *str)
218240
{
219241
char *result = strdup(str);
220242

221243
if (!result)
222244
{
223-
fprintf(stderr, "out of memory");
245+
fprintf(stderr, "out of memory\n");
224246
exit(1);
225247
}
226248
return result;
@@ -242,14 +264,8 @@ add_one_elt(char *eltname, eary *eary)
242264
else if (eary->num >= eary->alloc)
243265
{
244266
eary ->alloc *= 2;
245-
eary ->array = (char **)
246-
realloc(eary->array, eary->alloc * sizeof(char *));
247-
248-
if (!eary->array)
249-
{
250-
fprintf(stderr, "out of memory");
251-
exit(1);
252-
}
267+
eary ->array = (char **) pg_realloc(eary->array,
268+
eary->alloc * sizeof(char *));
253269
}
254270

255271
eary ->array[eary->num] = pg_strdup(eltname);

contrib/pg_upgrade/util.c

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -192,33 +192,39 @@ get_user_info(char **user_name)
192192

193193

194194
void *
195-
pg_malloc(size_t n)
195+
pg_malloc(size_t size)
196196
{
197-
void *p = malloc(n);
197+
void *p;
198198

199+
/* Avoid unportable behavior of malloc(0) */
200+
if (size == 0)
201+
size = 1;
202+
p = malloc(size);
199203
if (p == NULL)
200204
pg_log(PG_FATAL, "%s: out of memory\n", os_info.progname);
201-
202205
return p;
203206
}
204207

205208
void *
206-
pg_realloc(void *ptr, size_t n)
209+
pg_realloc(void *ptr, size_t size)
207210
{
208-
void *p = realloc(ptr, n);
211+
void *p;
209212

213+
/* Avoid unportable behavior of realloc(NULL, 0) */
214+
if (ptr == NULL && size == 0)
215+
size = 1;
216+
p = realloc(ptr, size);
210217
if (p == NULL)
211218
pg_log(PG_FATAL, "%s: out of memory\n", os_info.progname);
212-
213219
return p;
214220
}
215221

216222

217223
void
218-
pg_free(void *p)
224+
pg_free(void *ptr)
219225
{
220-
if (p != NULL)
221-
free(p);
226+
if (ptr != NULL)
227+
free(ptr);
222228
}
223229

224230

contrib/pgbench/pgbench.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,9 @@ pg_malloc(size_t size)
299299
{
300300
void *result;
301301

302+
/* Avoid unportable behavior of malloc(0) */
303+
if (size == 0)
304+
size = 1;
302305
result = malloc(size);
303306
if (!result)
304307
{
@@ -313,6 +316,9 @@ pg_realloc(void *ptr, size_t size)
313316
{
314317
void *result;
315318

319+
/* Avoid unportable behavior of realloc(NULL, 0) */
320+
if (ptr == NULL && size == 0)
321+
size = 1;
316322
result = realloc(ptr, size);
317323
if (!result)
318324
{

src/backend/utils/misc/guc.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3358,6 +3358,9 @@ guc_malloc(int elevel, size_t size)
33583358
{
33593359
void *data;
33603360

3361+
/* Avoid unportable behavior of malloc(0) */
3362+
if (size == 0)
3363+
size = 1;
33613364
data = malloc(size);
33623365
if (data == NULL)
33633366
ereport(elevel,
@@ -3371,6 +3374,9 @@ guc_realloc(int elevel, void *old, size_t size)
33713374
{
33723375
void *data;
33733376

3377+
/* Avoid unportable behavior of realloc(NULL, 0) */
3378+
if (old == NULL && size == 0)
3379+
size = 1;
33743380
data = realloc(old, size);
33753381
if (data == NULL)
33763382
ereport(elevel,

src/bin/initdb/initdb.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,9 @@ pg_malloc(size_t size)
294294
{
295295
void *result;
296296

297+
/* Avoid unportable behavior of malloc(0) */
298+
if (size == 0)
299+
size = 1;
297300
result = malloc(size);
298301
if (!result)
299302
{

src/bin/pg_basebackup/streamutil.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ pg_malloc0(size_t size)
5454
{
5555
void *result;
5656

57+
/* Avoid unportable behavior of malloc(0) */
58+
if (size == 0)
59+
size = 1;
5760
result = malloc(size);
5861
if (!result)
5962
{

src/bin/pg_ctl/pg_ctl.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,9 @@ pg_malloc(size_t size)
233233
{
234234
void *result;
235235

236+
/* Avoid unportable behavior of malloc(0) */
237+
if (size == 0)
238+
size = 1;
236239
result = malloc(size);
237240
if (!result)
238241
{

src/bin/pg_dump/dumpmem.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ pg_malloc(size_t size)
4242
{
4343
void *tmp;
4444

45+
/* Avoid unportable behavior of malloc(0) */
46+
if (size == 0)
47+
size = 1;
4548
tmp = malloc(size);
4649
if (!tmp)
4750
exit_horribly(NULL, "out of memory\n");
@@ -63,6 +66,9 @@ pg_realloc(void *ptr, size_t size)
6366
{
6467
void *tmp;
6568

69+
/* Avoid unportable behavior of realloc(NULL, 0) */
70+
if (ptr == NULL && size == 0)
71+
size = 1;
6672
tmp = realloc(ptr, size);
6773
if (!tmp)
6874
exit_horribly(NULL, "out of memory\n");

src/bin/psql/common.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ pg_malloc(size_t size)
6060
{
6161
void *tmp;
6262

63+
/* Avoid unportable behavior of malloc(0) */
64+
if (size == 0)
65+
size = 1;
6366
tmp = malloc(size);
6467
if (!tmp)
6568
{

src/bin/scripts/common.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,9 @@ pg_malloc(size_t size)
304304
{
305305
void *tmp;
306306

307+
/* Avoid unportable behavior of malloc(0) */
308+
if (size == 0)
309+
size = 1;
307310
tmp = malloc(size);
308311
if (!tmp)
309312
{

src/port/dirmod.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,11 @@ fe_palloc(Size size)
7070
{
7171
void *res;
7272

73-
if ((res = malloc(size)) == NULL)
73+
/* Avoid unportable behavior of malloc(0) */
74+
if (size == 0)
75+
size = 1;
76+
res = malloc(size);
77+
if (res == NULL)
7478
{
7579
fprintf(stderr, _("out of memory\n"));
7680
exit(1);
@@ -96,7 +100,11 @@ fe_repalloc(void *pointer, Size size)
96100
{
97101
void *res;
98102

99-
if ((res = realloc(pointer, size)) == NULL)
103+
/* Avoid unportable behavior of realloc(NULL, 0) */
104+
if (pointer == NULL && size == 0)
105+
size = 1;
106+
res = realloc(pointer, size);
107+
if (res == NULL)
100108
{
101109
fprintf(stderr, _("out of memory\n"));
102110
exit(1);

0 commit comments

Comments
 (0)