From 0db1a951d5bb7617bbf2bd0b30a9f0971c2ce11d Mon Sep 17 00:00:00 2001 From: Tom Lane 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 daf66621fa..6becfd0dbc 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 #include +#include #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 7e73539912..18be70ea92 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 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! -- 2.40.0