From 340b66cc700623bffb794643e44a50055337b6a4 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Mon, 6 May 2002 17:34:45 +0000
Subject: [PATCH] Cause fmtId to always use its internal buffer for the
 returned value, in hopes of making erroneous usage more apparent.  Per
 discussion 15-Apr.

---
 src/bin/pg_dump/pg_backup_archiver.c | 55 +++++++++++++++-------------
 1 file changed, 30 insertions(+), 25 deletions(-)

diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c
index 14ce1370516..11c62a0298c 100644
--- a/src/bin/pg_dump/pg_backup_archiver.c
+++ b/src/bin/pg_dump/pg_backup_archiver.c
@@ -15,7 +15,7 @@
  *
  *
  * IDENTIFICATION
- *		$Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.44 2002/04/24 14:03:22 momjian Exp $
+ *		$Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.45 2002/05/06 17:34:45 tgl Exp $
  *
  * Modifications - 28-Jun-2000 - pjw@rhyme.com.au
  *
@@ -2069,11 +2069,12 @@ _reconnectAsOwner(ArchiveHandle *AH, const char *dbname, TocEntry *te)
 /*
  * fmtId
  *
- *	checks input string for non-lowercase characters
- *	returns pointer to input string or string surrounded by double quotes
+ *	Quotes input string if it's not a legitimate SQL identifier as-is,
+ *	or all the time if force_quotes is true.
  *
- *	Note that the returned string should be used immediately since it
- *	uses a static buffer to hold the string. Non-reentrant but faster?
+ *	Note that the returned string must be used before calling fmtId again,
+ *	since we re-use the same return buffer each time.  Non-reentrant but
+ *	avoids memory leakage.
  */
 const char *
 fmtId(const char *rawid, bool force_quotes)
@@ -2081,13 +2082,19 @@ fmtId(const char *rawid, bool force_quotes)
 	static PQExpBuffer id_return = NULL;
 	const char *cp;
 
+	if (id_return)				/* first time through? */
+		resetPQExpBuffer(id_return);
+	else
+		id_return = createPQExpBuffer();
+
 	if (!force_quotes)
 	{
 		/* do a quick check on the first character... */
-		if (!islower((unsigned char) *rawid))
+		if (!islower((unsigned char) *rawid) && *rawid != '_')
 			force_quotes = true;
-		/* otherwise check the entire string */
 		else
+		{
+			/* otherwise check the entire string */
 			for (cp = rawid; *cp; cp++)
 			{
 				if (!(islower((unsigned char) *cp) ||
@@ -2098,32 +2105,30 @@ fmtId(const char *rawid, bool force_quotes)
 					break;
 				}
 			}
+		}
 	}
 
 	if (!force_quotes)
-		return rawid;			/* no quoting needed */
-
-	if (id_return)
-		resetPQExpBuffer(id_return);
+	{
+		/* no quoting needed */
+		appendPQExpBufferStr(id_return, rawid);
+	}
 	else
-		id_return = createPQExpBuffer();
-
-	appendPQExpBufferChar(id_return, '\"');
-	for (cp = rawid; *cp; cp++)
 	{
-		/*
-		 * Did we find a double-quote in the string? Then make this a
-		 * double double-quote per SQL99. Before, we put in a
-		 * backslash/double-quote pair. - thomas 2000-08-05
-		 */
-		if (*cp == '\"')
+		appendPQExpBufferChar(id_return, '\"');
+		for (cp = rawid; *cp; cp++)
 		{
-			appendPQExpBufferChar(id_return, '\"');
-			appendPQExpBufferChar(id_return, '\"');
+			/*
+			 * Did we find a double-quote in the string? Then make this a
+			 * double double-quote per SQL99. Before, we put in a
+			 * backslash/double-quote pair. - thomas 2000-08-05
+			 */
+			if (*cp == '\"')
+				appendPQExpBufferChar(id_return, '\"');
+			appendPQExpBufferChar(id_return, *cp);
 		}
-		appendPQExpBufferChar(id_return, *cp);
+		appendPQExpBufferChar(id_return, '\"');
 	}
-	appendPQExpBufferChar(id_return, '\"');
 
 	return id_return->data;
 }
-- 
GitLab