From 0db1a951d5bb7617bbf2bd0b30a9f0971c2ce11d Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Fri, 22 Dec 2000 21:36:09 +0000
Subject: [PATCH] Repair not-too-well-thought-out code to do rangechecking of
 OIDs on 64-bit machines.  Also, make oidvectorin use the same code as oidin.

---
 src/backend/utils/adt/oid.c | 140 ++++++++++++++++++++++--------------
 src/include/postgres_ext.h  |  12 +++-
 2 files changed, 98 insertions(+), 54 deletions(-)

diff --git a/src/backend/utils/adt/oid.c b/src/backend/utils/adt/oid.c
index daf66621fa8..6becfd0dbc7 100644
--- a/src/backend/utils/adt/oid.c
+++ b/src/backend/utils/adt/oid.c
@@ -1,14 +1,14 @@
 /*-------------------------------------------------------------------------
  *
  * oid.c
- *	  Functions for the built-in type Oid.
+ *	  Functions for the built-in type Oid ... also oidvector.
  *
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/oid.c,v 1.41 2000/12/03 20:45:36 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/oid.c,v 1.42 2000/12/22 21:36:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,6 +16,7 @@
 
 #include <ctype.h>
 #include <errno.h>
+#include <limits.h>
 
 #include "utils/builtins.h"
 
@@ -23,6 +24,85 @@
  *	 USER I/O ROUTINES														 *
  *****************************************************************************/
 
+static Oid
+oidin_subr(const char *funcname, const char *s, char **endloc)
+{
+	unsigned long cvt;
+	char	   *endptr;
+	Oid			result;
+
+	errno = 0;
+
+	cvt = strtoul(s, &endptr, 10);
+
+	/*
+	 * strtoul() normally only sets ERANGE.  On some systems it also
+	 * may set EINVAL, which simply means it couldn't parse the
+	 * input string.  This is handled by the second "if" consistent
+	 * across platforms.  Note that for historical reasons we accept
+	 * an empty string as meaning 0.
+	 */
+	if (errno && errno != EINVAL)
+		elog(ERROR, "%s: error reading \"%s\": %m",
+			 funcname, s);
+	if (endptr == s && *endptr)
+		elog(ERROR, "%s: error in \"%s\": can't parse \"%s\"",
+			 funcname, s, endptr);
+
+	if (endloc)
+	{
+		/* caller wants to deal with rest of string */
+		*endloc = endptr;
+	}
+	else
+	{
+		/* allow only whitespace after number */
+		while (*endptr && isspace((unsigned char) *endptr))
+			endptr++;
+		if (*endptr)
+			elog(ERROR, "%s: error in \"%s\": can't parse \"%s\"",
+				 funcname, s, endptr);
+	}
+
+	result = (Oid) cvt;
+
+	/*
+	 * Cope with possibility that unsigned long is wider than Oid.
+	 *
+	 * To ensure consistent results on 32-bit and 64-bit platforms,
+	 * make sure the error message is the same as if strtoul() had
+	 * returned ERANGE.
+	 */
+#if OID_MAX < ULONG_MAX
+	if (cvt > (unsigned long) OID_MAX)
+		elog(ERROR, "%s: error reading \"%s\": %s",
+			 funcname, s, strerror(ERANGE));
+#endif
+
+	return result;
+}
+
+Datum
+oidin(PG_FUNCTION_ARGS)
+{
+	char	   *s = PG_GETARG_CSTRING(0);
+	Oid			result;
+
+	result = oidin_subr("oidin", s, NULL);
+	PG_RETURN_OID(result);
+}
+
+Datum
+oidout(PG_FUNCTION_ARGS)
+{
+	Oid			o = PG_GETARG_OID(0);
+	char	   *result = (char *) palloc(12);
+
+	snprintf(result, 12, "%u", o);
+	PG_RETURN_CSTRING(result);
+}
+
+
 /*
  *		oidvectorin			- converts "num num ..." to internal form
  *
@@ -38,14 +118,13 @@ oidvectorin(PG_FUNCTION_ARGS)
 
 	result = (Oid *) palloc(sizeof(Oid[INDEX_MAX_KEYS]));
 
-	for (slot = 0; *oidString && slot < INDEX_MAX_KEYS; slot++)
+	for (slot = 0; slot < INDEX_MAX_KEYS; slot++)
 	{
-		if (sscanf(oidString, "%u", &result[slot]) != 1)
-			break;
 		while (*oidString && isspace((unsigned char) *oidString))
 			oidString++;
-		while (*oidString && isdigit((unsigned char) *oidString))
-			oidString++;
+		if (*oidString == '\0')
+			break;
+		result[slot] = oidin_subr("oidvectorin", oidString, &oidString);
 	}
 	while (*oidString && isspace((unsigned char) *oidString))
 		oidString++;
@@ -88,49 +167,6 @@ oidvectorout(PG_FUNCTION_ARGS)
 	PG_RETURN_CSTRING(result);
 }
 
-Datum
-oidin(PG_FUNCTION_ARGS)
-{
-	char	   *s = PG_GETARG_CSTRING(0);
-	unsigned long cvt;
-	char	   *endptr;
-	Oid			result;
-
-	errno = 0;
-
-	cvt = strtoul(s, &endptr, 10);
-
-	/*
-	 * strtoul() normally only sets ERANGE.  On some systems it also
-	 * may set EINVAL, which simply means it couldn't parse the
-	 * input string.  This is handled by the second "if" consistent
-	 * across platforms.
-	 */
-	if (errno && errno != EINVAL)
-		elog(ERROR, "oidin: error reading \"%s\": %m", s);
-	if (endptr && *endptr)
-		elog(ERROR, "oidin: error in \"%s\": can't parse \"%s\"", s, endptr);
-
-	/*
-	 * Cope with possibility that unsigned long is wider than Oid.
-	 */
-	result = (Oid) cvt;
-	if ((unsigned long) result != cvt)
-		elog(ERROR, "oidin: error reading \"%s\": value too large", s);
-
-	return ObjectIdGetDatum(result);
-}
-
-Datum
-oidout(PG_FUNCTION_ARGS)
-{
-	Oid			o = PG_GETARG_OID(0);
-	char	   *result = (char *) palloc(12);
-
-	snprintf(result, 12, "%u", o);
-	PG_RETURN_CSTRING(result);
-}
-
 /*****************************************************************************
  *	 PUBLIC ROUTINES														 *
  *****************************************************************************/
@@ -294,8 +330,8 @@ text_oid(PG_FUNCTION_ARGS)
 	memcpy(str, VARDATA(string), len);
 	*(str + len) = '\0';
 
-	result = DatumGetObjectId(DirectFunctionCall1(oidin,
-												  CStringGetDatum(str)));
+	result = oidin_subr("text_oid", str, NULL);
+
 	pfree(str);
 
 	PG_RETURN_OID(result);
diff --git a/src/include/postgres_ext.h b/src/include/postgres_ext.h
index 7e73539912a..18be70ea922 100644
--- a/src/include/postgres_ext.h
+++ b/src/include/postgres_ext.h
@@ -16,7 +16,7 @@
  *	use header files that are otherwise internal to Postgres to interface
  *	with the backend.
  *
- * $Id: postgres_ext.h,v 1.4 1999/06/04 21:12:07 tgl Exp $
+ * $Id: postgres_ext.h,v 1.5 2000/12/22 21:36:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -24,9 +24,17 @@
 #ifndef POSTGRES_EXT_H
 #define POSTGRES_EXT_H
 
+/*
+ * Object ID is a fundamental type in Postgres.
+ */
 typedef unsigned int Oid;
 
-/* NAMEDATALEN is the max length for system identifiers (e.g. table names,
+#define OID_MAX  UINT_MAX
+/* you will need to include <limits.h> to use the above #define */
+
+
+/*
+ * NAMEDATALEN is the max length for system identifiers (e.g. table names,
  * attribute names, function names, etc.)
  *
  * NOTE that databases with different NAMEDATALEN's cannot interoperate!
-- 
GitLab