1
0
mirror of https://github.com/postgres/postgres.git synced 2025-08-06 18:42:54 +03:00

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.
This commit is contained in:
Tom Lane
2012-10-02 17:31:49 -04:00
parent 87b6a3989f
commit 689d99306a
11 changed files with 106 additions and 43 deletions

View File

@@ -49,8 +49,9 @@ struct options
/* function prototypes */
static void help(const char *progname);
void get_opts(int, char **, struct options *);
void *myalloc(size_t size);
char *mystrdup(const char *str);
void *pg_malloc(size_t size);
void *pg_realloc(void *ptr, size_t size);
char *pg_strdup(const char *str);
void add_one_elt(char *eltname, eary *eary);
char *get_comma_elts(eary *eary);
PGconn *sql_conn(struct options *);
@@ -102,7 +103,7 @@ get_opts(int argc, char **argv, struct options * my_opts)
{
/* specify the database */
case 'd':
my_opts->dbname = mystrdup(optarg);
my_opts->dbname = pg_strdup(optarg);
break;
/* specify one tablename to show */
@@ -127,17 +128,17 @@ get_opts(int argc, char **argv, struct options * my_opts)
/* host to connect to */
case 'H':
my_opts->hostname = mystrdup(optarg);
my_opts->hostname = pg_strdup(optarg);
break;
/* port to connect to on remote host */
case 'p':
my_opts->port = mystrdup(optarg);
my_opts->port = pg_strdup(optarg);
break;
/* username */
case 'U':
my_opts->username = mystrdup(optarg);
my_opts->username = pg_strdup(optarg);
break;
/* display system tables */
@@ -199,26 +200,47 @@ help(const char *progname)
}
void *
myalloc(size_t size)
pg_malloc(size_t size)
{
void *ptr = malloc(size);
void *ptr;
/* Avoid unportable behavior of malloc(0) */
if (size == 0)
size = 1;
ptr = malloc(size);
if (!ptr)
{
fprintf(stderr, "out of memory");
fprintf(stderr, "out of memory\n");
exit(1);
}
return ptr;
}
void *
pg_realloc(void *ptr, size_t size)
{
void *result;
/* Avoid unportable behavior of realloc(NULL, 0) */
if (ptr == NULL && size == 0)
size = 1;
result = realloc(ptr, size);
if (!result)
{
fprintf(stderr, "out of memory\n");
exit(1);
}
return result;
}
char *
mystrdup(const char *str)
pg_strdup(const char *str)
{
char *result = strdup(str);
if (!result)
{
fprintf(stderr, "out of memory");
fprintf(stderr, "out of memory\n");
exit(1);
}
return result;
@@ -235,22 +257,16 @@ add_one_elt(char *eltname, eary *eary)
if (eary->alloc == 0)
{
eary ->alloc = 8;
eary ->array = (char **) myalloc(8 * sizeof(char *));
eary ->array = (char **) pg_malloc(8 * sizeof(char *));
}
else if (eary->num >= eary->alloc)
{
eary ->alloc *= 2;
eary ->array = (char **)
realloc(eary->array, eary->alloc * sizeof(char *));
if (!eary->array)
{
fprintf(stderr, "out of memory");
exit(1);
}
eary ->array = (char **) pg_realloc(eary->array,
eary->alloc * sizeof(char *));
}
eary ->array[eary->num] = mystrdup(eltname);
eary ->array[eary->num] = pg_strdup(eltname);
eary ->num++;
}
@@ -270,7 +286,7 @@ get_comma_elts(eary *eary)
length = 0;
if (eary->num == 0)
return mystrdup("");
return pg_strdup("");
/*
* PQescapeString wants 2 * length + 1 bytes of breath space. Add two
@@ -279,7 +295,7 @@ get_comma_elts(eary *eary)
for (i = 0; i < eary->num; i++)
length += strlen(eary->array[i]);
ret = (char *) myalloc(length * 2 + 4 * eary->num);
ret = (char *) pg_malloc(length * 2 + 4 * eary->num);
ptr = ret;
for (i = 0; i < eary->num; i++)
@@ -384,7 +400,7 @@ sql_exec(PGconn *conn, const char *todo, bool quiet)
nfields = PQnfields(res);
/* for each field, get the needed width */
length = (int *) myalloc(sizeof(int) * nfields);
length = (int *) pg_malloc(sizeof(int) * nfields);
for (j = 0; j < nfields; j++)
length[j] = strlen(PQfname(res, j));
@@ -407,7 +423,7 @@ sql_exec(PGconn *conn, const char *todo, bool quiet)
l += length[j] + 2;
}
fprintf(stdout, "\n");
pad = (char *) myalloc(l + 1);
pad = (char *) pg_malloc(l + 1);
MemSet(pad, '-', l);
pad[l] = '\0';
fprintf(stdout, "%s\n", pad);
@@ -498,7 +514,7 @@ sql_exec_searchtables(PGconn *conn, struct options * opts)
comma_filenodes = get_comma_elts(opts->filenodes);
/* 80 extra chars for SQL expression */
qualifiers = (char *) myalloc(strlen(comma_oids) + strlen(comma_tables) +
qualifiers = (char *) pg_malloc(strlen(comma_oids) + strlen(comma_tables) +
strlen(comma_filenodes) + 80);
ptr = qualifiers;
@@ -525,7 +541,7 @@ sql_exec_searchtables(PGconn *conn, struct options * opts)
free(comma_filenodes);
/* now build the query */
todo = (char *) myalloc(650 + strlen(qualifiers));
todo = (char *) pg_malloc(650 + strlen(qualifiers));
snprintf(todo, 650 + strlen(qualifiers),
"SELECT pg_catalog.pg_relation_filenode(c.oid) as \"Filenode\", relname as \"Table Name\" %s\n"
"FROM pg_catalog.pg_class c \n"
@@ -565,11 +581,11 @@ main(int argc, char **argv)
struct options *my_opts;
PGconn *pgconn;
my_opts = (struct options *) myalloc(sizeof(struct options));
my_opts = (struct options *) pg_malloc(sizeof(struct options));
my_opts->oids = (eary *) myalloc(sizeof(eary));
my_opts->tables = (eary *) myalloc(sizeof(eary));
my_opts->filenodes = (eary *) myalloc(sizeof(eary));
my_opts->oids = (eary *) pg_malloc(sizeof(eary));
my_opts->tables = (eary *) pg_malloc(sizeof(eary));
my_opts->filenodes = (eary *) pg_malloc(sizeof(eary));
my_opts->oids->num = my_opts->oids->alloc = 0;
my_opts->tables->num = my_opts->tables->alloc = 0;

View File

@@ -192,33 +192,39 @@ get_user_info(char **user_name)
void *
pg_malloc(size_t n)
pg_malloc(size_t size)
{
void *p = malloc(n);
void *p;
/* Avoid unportable behavior of malloc(0) */
if (size == 0)
size = 1;
p = malloc(size);
if (p == NULL)
pg_log(PG_FATAL, "%s: out of memory\n", os_info.progname);
return p;
}
void *
pg_realloc(void *ptr, size_t n)
pg_realloc(void *ptr, size_t size)
{
void *p = realloc(ptr, n);
void *p;
/* Avoid unportable behavior of realloc(NULL, 0) */
if (ptr == NULL && size == 0)
size = 1;
p = realloc(ptr, size);
if (p == NULL)
pg_log(PG_FATAL, "%s: out of memory\n", os_info.progname);
return p;
}
void
pg_free(void *p)
pg_free(void *ptr)
{
if (p != NULL)
free(p);
if (ptr != NULL)
free(ptr);
}

View File

@@ -295,6 +295,9 @@ xmalloc(size_t size)
{
void *result;
/* Avoid unportable behavior of malloc(0) */
if (size == 0)
size = 1;
result = malloc(size);
if (!result)
{
@@ -309,6 +312,9 @@ xrealloc(void *ptr, size_t size)
{
void *result;
/* Avoid unportable behavior of realloc(NULL, 0) */
if (ptr == NULL && size == 0)
size = 1;
result = realloc(ptr, size);
if (!result)
{

View File

@@ -3352,6 +3352,9 @@ guc_malloc(int elevel, size_t size)
{
void *data;
/* Avoid unportable behavior of malloc(0) */
if (size == 0)
size = 1;
data = malloc(size);
if (data == NULL)
ereport(elevel,
@@ -3365,6 +3368,9 @@ guc_realloc(int elevel, void *old, size_t size)
{
void *data;
/* Avoid unportable behavior of realloc(NULL, 0) */
if (old == NULL && size == 0)
size = 1;
data = realloc(old, size);
if (data == NULL)
ereport(elevel,

View File

@@ -285,6 +285,9 @@ pg_malloc(size_t size)
{
void *result;
/* Avoid unportable behavior of malloc(0) */
if (size == 0)
size = 1;
result = malloc(size);
if (!result)
{

View File

@@ -54,6 +54,9 @@ xmalloc0(int size)
{
void *result;
/* Avoid unportable behavior of malloc(0) */
if (size == 0)
size = 1;
result = malloc(size);
if (!result)
{

View File

@@ -233,6 +233,9 @@ pg_malloc(size_t size)
{
void *result;
/* Avoid unportable behavior of malloc(0) */
if (size == 0)
size = 1;
result = malloc(size);
if (!result)
{

View File

@@ -42,6 +42,9 @@ pg_malloc(size_t size)
{
void *tmp;
/* Avoid unportable behavior of malloc(0) */
if (size == 0)
size = 1;
tmp = malloc(size);
if (!tmp)
exit_horribly(NULL, "out of memory\n");
@@ -64,6 +67,9 @@ pg_realloc(void *ptr, size_t size)
{
void *tmp;
/* Avoid unportable behavior of realloc(NULL, 0) */
if (ptr == NULL && size == 0)
size = 1;
tmp = realloc(ptr, size);
if (!tmp)
exit_horribly(NULL, "out of memory\n");

View File

@@ -60,6 +60,9 @@ pg_malloc(size_t size)
{
void *tmp;
/* Avoid unportable behavior of malloc(0) */
if (size == 0)
size = 1;
tmp = malloc(size);
if (!tmp)
{

View File

@@ -136,6 +136,9 @@ pg_local_malloc(size_t size)
{
void *tmp;
/* Avoid unportable behavior of malloc(0) */
if (size == 0)
size = 1;
tmp = malloc(size);
if (!tmp)
{

View File

@@ -70,7 +70,11 @@ fe_palloc(Size size)
{
void *res;
if ((res = malloc(size)) == NULL)
/* Avoid unportable behavior of malloc(0) */
if (size == 0)
size = 1;
res = malloc(size);
if (res == NULL)
{
fprintf(stderr, _("out of memory\n"));
exit(1);
@@ -96,7 +100,11 @@ fe_repalloc(void *pointer, Size size)
{
void *res;
if ((res = realloc(pointer, size)) == NULL)
/* Avoid unportable behavior of realloc(NULL, 0) */
if (pointer == NULL && size == 0)
size = 1;
res = realloc(pointer, size);
if (res == NULL)
{
fprintf(stderr, _("out of memory\n"));
exit(1);