On Fri, Jun 10, 2011 at 21:07, Tom Lane <t...@sss.pgh.pa.us> wrote:
> Magnus Hagander <mag...@hagander.net> writes:
>> I came across a situation today with a pretty bad crash of pg_dump,
>> due to not checking the return code from malloc(). When looking
>> through the code, it seems there are a *lot* of places in pg_dump that
>> doesn't check the malloc return code.
>
>> But we do have a pg_malloc() function in there - but from what I can
>> tell it's only used very sparsely?
>
>> Shouldn't we be using that one more or less everywhere
>
> Yup.  Have at it.

Something along the line of this?

-- 
 Magnus Hagander
 Me: http://www.hagander.net/
 Work: http://www.redpill-linpro.com/
diff --git a/src/bin/pg_dump/Makefile b/src/bin/pg_dump/Makefile
index 8410af1..0737505 100644
--- a/src/bin/pg_dump/Makefile
+++ b/src/bin/pg_dump/Makefile
@@ -20,7 +20,7 @@ override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS)
 
 OBJS=	pg_backup_archiver.o pg_backup_db.o pg_backup_custom.o \
 	pg_backup_files.o pg_backup_null.o pg_backup_tar.o \
-	pg_backup_directory.o dumputils.o compress_io.o $(WIN32RES)
+	pg_backup_directory.o pg_dump_alloc.o dumputils.o compress_io.o $(WIN32RES)
 
 KEYWRDOBJS = keywords.o kwlookup.o
 
@@ -35,8 +35,8 @@ pg_dump: pg_dump.o common.o pg_dump_sort.o $(OBJS) $(KEYWRDOBJS) | submake-libpq
 pg_restore: pg_restore.o $(OBJS) $(KEYWRDOBJS) | submake-libpq submake-libpgport
 	$(CC) $(CFLAGS) pg_restore.o $(KEYWRDOBJS) $(OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
 
-pg_dumpall: pg_dumpall.o dumputils.o $(KEYWRDOBJS) | submake-libpq submake-libpgport
-	$(CC) $(CFLAGS) pg_dumpall.o dumputils.o $(KEYWRDOBJS) $(WIN32RES) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
+pg_dumpall: pg_dumpall.o dumputils.o pg_dump_alloc.o $(KEYWRDOBJS) | submake-libpq submake-libpgport
+	$(CC) $(CFLAGS) pg_dumpall.o dumputils.o pg_dump_alloc.o $(KEYWRDOBJS) $(WIN32RES) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
 
 install: all installdirs
 	$(INSTALL_PROGRAM) pg_dump$(X) '$(DESTDIR)$(bindir)'/pg_dump$(X)
diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c
index a631f64..b194f24 100644
--- a/src/bin/pg_dump/common.c
+++ b/src/bin/pg_dump/common.c
@@ -980,57 +980,3 @@ simple_string_list_member(SimpleStringList *list, const char *val)
 }
 
 
-/*
- * Safer versions of some standard C library functions. If an
- * out-of-memory condition occurs, these functions will bail out
- * safely; therefore, their return value is guaranteed to be non-NULL.
- *
- * XXX need to refactor things so that these can be in a file that can be
- * shared by pg_dumpall and pg_restore as well as pg_dump.
- */
-
-char *
-pg_strdup(const char *string)
-{
-	char	   *tmp;
-
-	if (!string)
-		exit_horribly(NULL, NULL, "cannot duplicate null pointer\n");
-	tmp = strdup(string);
-	if (!tmp)
-		exit_horribly(NULL, NULL, "out of memory\n");
-	return tmp;
-}
-
-void *
-pg_malloc(size_t size)
-{
-	void	   *tmp;
-
-	tmp = malloc(size);
-	if (!tmp)
-		exit_horribly(NULL, NULL, "out of memory\n");
-	return tmp;
-}
-
-void *
-pg_calloc(size_t nmemb, size_t size)
-{
-	void	   *tmp;
-
-	tmp = calloc(nmemb, size);
-	if (!tmp)
-		exit_horribly(NULL, NULL, "out of memory\n");
-	return tmp;
-}
-
-void *
-pg_realloc(void *ptr, size_t size)
-{
-	void	   *tmp;
-
-	tmp = realloc(ptr, size);
-	if (!tmp)
-		exit_horribly(NULL, NULL, "out of memory\n");
-	return tmp;
-}
diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c
index 0e1037c..78b5e93 100644
--- a/src/bin/pg_dump/pg_backup_archiver.c
+++ b/src/bin/pg_dump/pg_backup_archiver.c
@@ -735,8 +735,6 @@ ArchiveEntry(Archive *AHX,
 	TocEntry   *newToc;
 
 	newToc = (TocEntry *) calloc(1, sizeof(TocEntry));
-	if (!newToc)
-		die_horribly(AH, modulename, "out of memory\n");
 
 	AH->tocCount++;
 	if (dumpId > AH->maxDumpId)
@@ -1131,8 +1129,6 @@ archprintf(Archive *AH, const char *fmt,...)
 			free(p);
 		bSize *= 2;
 		p = (char *) malloc(bSize);
-		if (p == NULL)
-			exit_horribly(AH, modulename, "out of memory\n");
 		va_start(ap, fmt);
 		cnt = vsnprintf(p, bSize, fmt, ap);
 		va_end(ap);
@@ -1266,8 +1262,6 @@ ahprintf(ArchiveHandle *AH, const char *fmt,...)
 			free(p);
 		bSize *= 2;
 		p = (char *) malloc(bSize);
-		if (p == NULL)
-			die_horribly(AH, modulename, "out of memory\n");
 		va_start(ap, fmt);
 		cnt = vsnprintf(p, bSize, fmt, ap);
 		va_end(ap);
@@ -1736,8 +1730,6 @@ ReadStr(ArchiveHandle *AH)
 	else
 	{
 		buf = (char *) malloc(l + 1);
-		if (!buf)
-			die_horribly(AH, modulename, "out of memory\n");
 
 		if ((*AH->ReadBufPtr) (AH, (void *) buf, l) != l)
 			die_horribly(AH, modulename, "unexpected end of file\n");
@@ -1930,8 +1922,6 @@ _allocAH(const char *FileSpec, const ArchiveFormat fmt,
 #endif
 
 	AH = (ArchiveHandle *) calloc(1, sizeof(ArchiveHandle));
-	if (!AH)
-		die_horribly(AH, modulename, "out of memory\n");
 
 	/* AH->debugLevel = 100; */
 
@@ -1976,8 +1966,6 @@ _allocAH(const char *FileSpec, const ArchiveFormat fmt,
 	AH->currWithOids = -1;		/* force SET */
 
 	AH->toc = (TocEntry *) calloc(1, sizeof(TocEntry));
-	if (!AH->toc)
-		die_horribly(AH, modulename, "out of memory\n");
 
 	AH->toc->next = AH->toc;
 	AH->toc->prev = AH->toc;
@@ -4195,8 +4183,6 @@ CloneArchive(ArchiveHandle *AH)
 
 	/* Make a "flat" copy */
 	clone = (ArchiveHandle *) malloc(sizeof(ArchiveHandle));
-	if (clone == NULL)
-		die_horribly(AH, modulename, "out of memory\n");
 	memcpy(clone, AH, sizeof(ArchiveHandle));
 
 	/* Handle format-independent fields */
diff --git a/src/bin/pg_dump/pg_backup_custom.c b/src/bin/pg_dump/pg_backup_custom.c
index 01d5e37..e1635ae 100644
--- a/src/bin/pg_dump/pg_backup_custom.c
+++ b/src/bin/pg_dump/pg_backup_custom.c
@@ -128,15 +128,11 @@ InitArchiveFmt_Custom(ArchiveHandle *AH)
 
 	/* Set up a private area. */
 	ctx = (lclContext *) calloc(1, sizeof(lclContext));
-	if (ctx == NULL)
-		die_horribly(AH, modulename, "out of memory\n");
 	AH->formatData = (void *) ctx;
 
 	/* Initialize LO buffering */
 	AH->lo_buf_size = LOBBUFSIZE;
 	AH->lo_buf = (void *) malloc(LOBBUFSIZE);
-	if (AH->lo_buf == NULL)
-		die_horribly(AH, modulename, "out of memory\n");
 
 	ctx->filePos = 0;
 
@@ -771,8 +767,6 @@ _Clone(ArchiveHandle *AH)
 	lclContext *ctx = (lclContext *) AH->formatData;
 
 	AH->formatData = (lclContext *) malloc(sizeof(lclContext));
-	if (AH->formatData == NULL)
-		die_horribly(AH, modulename, "out of memory\n");
 	memcpy(AH->formatData, ctx, sizeof(lclContext));
 	ctx = (lclContext *) AH->formatData;
 
@@ -898,8 +892,6 @@ _CustomReadFunc(ArchiveHandle *AH, char **buf, size_t *buflen)
 	{
 		free(*buf);
 		*buf = (char *) malloc(blkLen);
-		if (!(*buf))
-			die_horribly(AH, modulename, "out of memory\n");
 		*buflen = blkLen;
 	}
 
diff --git a/src/bin/pg_dump/pg_backup_db.c b/src/bin/pg_dump/pg_backup_db.c
index cc3882c..67deaa7 100644
--- a/src/bin/pg_dump/pg_backup_db.c
+++ b/src/bin/pg_dump/pg_backup_db.c
@@ -160,9 +160,6 @@ _connectDB(ArchiveHandle *AH, const char *reqdb, const char *requser)
 		const char **keywords = malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords));
 		const char **values = malloc(PARAMS_ARRAY_SIZE * sizeof(*values));
 
-		if (!keywords || !values)
-			die_horribly(AH, modulename, "out of memory\n");
-
 		keywords[0] = "host";
 		values[0] = PQhost(AH->connection);
 		keywords[1] = "port";
@@ -267,9 +264,6 @@ ConnectDatabase(Archive *AHX,
 		const char **keywords = malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords));
 		const char **values = malloc(PARAMS_ARRAY_SIZE * sizeof(*values));
 
-		if (!keywords || !values)
-			die_horribly(AH, modulename, "out of memory\n");
-
 		keywords[0] = "host";
 		values[0] = pghost;
 		keywords[1] = "port";
diff --git a/src/bin/pg_dump/pg_backup_directory.c b/src/bin/pg_dump/pg_backup_directory.c
index 111c3e8..b0bdf5f 100644
--- a/src/bin/pg_dump/pg_backup_directory.c
+++ b/src/bin/pg_dump/pg_backup_directory.c
@@ -127,8 +127,6 @@ InitArchiveFmt_Directory(ArchiveHandle *AH)
 
 	/* Set up our private context */
 	ctx = (lclContext *) calloc(1, sizeof(lclContext));
-	if (ctx == NULL)
-		die_horribly(AH, modulename, "out of memory\n");
 	AH->formatData = (void *) ctx;
 
 	ctx->dataFH = NULL;
@@ -137,8 +135,6 @@ InitArchiveFmt_Directory(ArchiveHandle *AH)
 	/* Initialize LO buffering */
 	AH->lo_buf_size = LOBBUFSIZE;
 	AH->lo_buf = (void *) malloc(LOBBUFSIZE);
-	if (AH->lo_buf == NULL)
-		die_horribly(AH, modulename, "out of memory\n");
 
 	/*
 	 * Now open the TOC file
@@ -198,8 +194,6 @@ _ArchiveEntry(ArchiveHandle *AH, TocEntry *te)
 	char		fn[MAXPGPATH];
 
 	tctx = (lclTocEntry *) calloc(1, sizeof(lclTocEntry));
-	if (!tctx)
-		die_horribly(AH, modulename, "out of memory\n");
 	if (te->dataDumper)
 	{
 		snprintf(fn, MAXPGPATH, "%d.dat", te->dumpId);
@@ -249,8 +243,6 @@ _ReadExtraToc(ArchiveHandle *AH, TocEntry *te)
 	if (tctx == NULL)
 	{
 		tctx = (lclTocEntry *) calloc(1, sizeof(lclTocEntry));
-		if (!tctx)
-			die_horribly(AH, modulename, "out of memory\n");
 		te->formatData = (void *) tctx;
 	}
 
@@ -357,8 +349,6 @@ _PrintFileData(ArchiveHandle *AH, char *filename, RestoreOptions *ropt)
 					 filename, strerror(errno));
 
 	buf = malloc(ZLIB_OUT_SIZE);
-	if (buf == NULL)
-		die_horribly(NULL, modulename, "out of memory\n");
 	buflen = ZLIB_OUT_SIZE;
 
 	while ((cnt = cfread(buf, buflen, cfp)))
diff --git a/src/bin/pg_dump/pg_backup_files.c b/src/bin/pg_dump/pg_backup_files.c
index abc93b1..55dfab3 100644
--- a/src/bin/pg_dump/pg_backup_files.c
+++ b/src/bin/pg_dump/pg_backup_files.c
@@ -110,8 +110,6 @@ InitArchiveFmt_Files(ArchiveHandle *AH)
 	/* Initialize LO buffering */
 	AH->lo_buf_size = LOBBUFSIZE;
 	AH->lo_buf = (void *) malloc(LOBBUFSIZE);
-	if (AH->lo_buf == NULL)
-		die_horribly(AH, modulename, "out of memory\n");
 
 	/*
 	 * Now open the TOC file
diff --git a/src/bin/pg_dump/pg_backup_null.c b/src/bin/pg_dump/pg_backup_null.c
index bf1e6e6..1e86aaa 100644
--- a/src/bin/pg_dump/pg_backup_null.c
+++ b/src/bin/pg_dump/pg_backup_null.c
@@ -68,8 +68,6 @@ InitArchiveFmt_Null(ArchiveHandle *AH)
 	/* Initialize LO buffering */
 	AH->lo_buf_size = LOBBUFSIZE;
 	AH->lo_buf = (void *) malloc(LOBBUFSIZE);
-	if (AH->lo_buf == NULL)
-		die_horribly(AH, NULL, "out of memory\n");
 
 	/*
 	 * Now prevent reading...
diff --git a/src/bin/pg_dump/pg_backup_tar.c b/src/bin/pg_dump/pg_backup_tar.c
index 041f9f9..3c9e01d 100644
--- a/src/bin/pg_dump/pg_backup_tar.c
+++ b/src/bin/pg_dump/pg_backup_tar.c
@@ -167,8 +167,6 @@ InitArchiveFmt_Tar(ArchiveHandle *AH)
 	/* Initialize LO buffering */
 	AH->lo_buf_size = LOBBUFSIZE;
 	AH->lo_buf = (void *) malloc(LOBBUFSIZE);
-	if (AH->lo_buf == NULL)
-		die_horribly(AH, modulename, "out of memory\n");
 
 	/*
 	 * Now open the tar file, and load the TOC if we're in read mode.
@@ -1011,8 +1009,6 @@ tarPrintf(ArchiveHandle *AH, TAR_MEMBER *th, const char *fmt,...)
 			free(p);
 		bSize *= 2;
 		p = (char *) malloc(bSize);
-		if (p == NULL)
-			die_horribly(AH, modulename, "out of memory\n");
 		va_start(ap, fmt);
 		cnt = vsnprintf(p, bSize, fmt, ap);
 		va_end(ap);
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index c95614b..000e8e3 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -520,10 +520,23 @@ extern void simple_string_list_append(SimpleStringList *list, const char *val);
 extern bool simple_oid_list_member(SimpleOidList *list, Oid val);
 extern bool simple_string_list_member(SimpleStringList *list, const char *val);
 
+/*
+ * Redefinitions of the memory allocation functions that call
+ * die_horribly() when they fail instead of returning NULL.
+ */
 extern char *pg_strdup(const char *string);
 extern void *pg_malloc(size_t size);
 extern void *pg_calloc(size_t nmemb, size_t size);
 extern void *pg_realloc(void *ptr, size_t size);
+#ifndef PG_DUMP_NO_ALLOC_REDEFINE
+#ifdef strdup
+#undef strdup
+#endif
+#define strdup(x) pg_strdup(x)
+#define malloc(x) pg_malloc(x)
+#define calloc(x,y) pg_calloc(x, y)
+#define realloc(x,y) pg_realloc(x, y)
+#endif
 
 extern void check_conn_and_db(void);
 extern void exit_nicely(void);
diff --git a/src/bin/pg_dump/pg_dump_alloc.c b/src/bin/pg_dump/pg_dump_alloc.c
new file mode 100644
index 0000000..7b252a7
--- /dev/null
+++ b/src/bin/pg_dump/pg_dump_alloc.c
@@ -0,0 +1,54 @@
+#define PG_DUMP_NO_ALLOC_REDEFINE
+#include "pg_backup.h"
+
+/*
+ * Safer versions of some standard C library functions. If an
+ * out-of-memory condition occurs, these functions will bail out
+ * safely; therefore, their return value is guaranteed to be non-NULL.
+ */
+
+char *
+pg_strdup(const char *string)
+{
+	char	   *tmp;
+
+	if (!string)
+		exit_horribly(NULL, NULL, "cannot duplicate null pointer\n");
+	tmp = strdup(string);
+	if (!tmp)
+		exit_horribly(NULL, NULL, "out of memory\n");
+	return tmp;
+}
+
+void *
+pg_malloc(size_t size)
+{
+	void	   *tmp;
+
+	tmp = malloc(size);
+	if (!tmp)
+		exit_horribly(NULL, NULL, "out of memory\n");
+	return tmp;
+}
+
+void *
+pg_calloc(size_t nmemb, size_t size)
+{
+	void	   *tmp;
+
+	tmp = calloc(nmemb, size);
+	if (!tmp)
+		exit_horribly(NULL, NULL, "out of memory\n");
+	return tmp;
+}
+
+void *
+pg_realloc(void *ptr, size_t size)
+{
+	void	   *tmp;
+
+	tmp = realloc(ptr, size);
+	if (!tmp)
+		exit_horribly(NULL, NULL, "out of memory\n");
+	return tmp;
+}
diff --git a/src/bin/pg_dump/pg_dump_sort.c b/src/bin/pg_dump/pg_dump_sort.c
index 963f734..09acb51 100644
--- a/src/bin/pg_dump/pg_dump_sort.c
+++ b/src/bin/pg_dump/pg_dump_sort.c
@@ -228,8 +228,6 @@ sortDumpableObjects(DumpableObject **objs, int numObjs)
 		return;
 
 	ordering = (DumpableObject **) malloc(numObjs * sizeof(DumpableObject *));
-	if (ordering == NULL)
-		exit_horribly(NULL, modulename, "out of memory\n");
 
 	while (!TopoSort(objs, numObjs, ordering, &nOrdering))
 		findDependencyLoops(ordering, nOrdering, numObjs);
@@ -302,8 +300,6 @@ TopoSort(DumpableObject **objs,
 
 	/* Create workspace for the above-described heap */
 	pendingHeap = (int *) malloc(numObjs * sizeof(int));
-	if (pendingHeap == NULL)
-		exit_horribly(NULL, modulename, "out of memory\n");
 
 	/*
 	 * Scan the constraints, and for each item in the input, generate a count
@@ -313,12 +309,8 @@ TopoSort(DumpableObject **objs,
 	 * dumpId j.
 	 */
 	beforeConstraints = (int *) malloc((maxDumpId + 1) * sizeof(int));
-	if (beforeConstraints == NULL)
-		exit_horribly(NULL, modulename, "out of memory\n");
 	memset(beforeConstraints, 0, (maxDumpId + 1) * sizeof(int));
 	idMap = (int *) malloc((maxDumpId + 1) * sizeof(int));
-	if (idMap == NULL)
-		exit_horribly(NULL, modulename, "out of memory\n");
 	for (i = 0; i < numObjs; i++)
 	{
 		obj = objs[i];
@@ -517,8 +509,6 @@ findDependencyLoops(DumpableObject **objs, int nObjs, int totObjs)
 	int			i;
 
 	workspace = (DumpableObject **) malloc(totObjs * sizeof(DumpableObject *));
-	if (workspace == NULL)
-		exit_horribly(NULL, modulename, "out of memory\n");
 	initiallen = 0;
 	fixedloop = false;
 
diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c
index b3ad2ea..a47bf63 100644
--- a/src/bin/pg_dump/pg_dumpall.c
+++ b/src/bin/pg_dump/pg_dumpall.c
@@ -1646,12 +1646,6 @@ connectDatabase(const char *dbname, const char *pghost, const char *pgport,
 		const char **keywords = malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords));
 		const char **values = malloc(PARAMS_ARRAY_SIZE * sizeof(*values));
 
-		if (!keywords || !values)
-		{
-			fprintf(stderr, _("%s: out of memory\n"), progname);
-			exit(1);
-		}
-
 		keywords[0] = "host";
 		values[0] = pghost;
 		keywords[1] = "port";
@@ -1866,3 +1860,21 @@ doShellQuoting(PQExpBuffer buf, const char *str)
 	appendPQExpBufferChar(buf, '"');
 #endif   /* WIN32 */
 }
+
+/*
+ * exit_horribly() is called from the redefined memory allocation
+ * routines if we run out of memory.
+ */
+void
+exit_horribly(Archive *AH, const char *modulename, const char *fmt,...)
+{
+	va_list		ap;
+
+	fprintf(stderr, "%s: ", progname);
+
+	va_start(ap, fmt);
+	vfprintf(stderr, _(fmt), ap);
+	va_end(ap);
+
+	exit(1);
+}
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to