mirror of
https://github.com/postgres/postgres.git
synced 2025-05-06 19:59:18 +03:00
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.
This commit is contained in:
parent
369aace5f3
commit
0db1a951d5
@ -1,14 +1,14 @@
|
|||||||
/*-------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* oid.c
|
* 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) 1996-2000, PostgreSQL, Inc
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
|
|
||||||
@ -23,6 +24,85 @@
|
|||||||
* USER I/O ROUTINES *
|
* 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
|
* oidvectorin - converts "num num ..." to internal form
|
||||||
*
|
*
|
||||||
@ -38,14 +118,13 @@ oidvectorin(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
result = (Oid *) palloc(sizeof(Oid[INDEX_MAX_KEYS]));
|
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))
|
while (*oidString && isspace((unsigned char) *oidString))
|
||||||
oidString++;
|
oidString++;
|
||||||
while (*oidString && isdigit((unsigned char) *oidString))
|
if (*oidString == '\0')
|
||||||
oidString++;
|
break;
|
||||||
|
result[slot] = oidin_subr("oidvectorin", oidString, &oidString);
|
||||||
}
|
}
|
||||||
while (*oidString && isspace((unsigned char) *oidString))
|
while (*oidString && isspace((unsigned char) *oidString))
|
||||||
oidString++;
|
oidString++;
|
||||||
@ -88,49 +167,6 @@ oidvectorout(PG_FUNCTION_ARGS)
|
|||||||
PG_RETURN_CSTRING(result);
|
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 *
|
* PUBLIC ROUTINES *
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
@ -294,8 +330,8 @@ text_oid(PG_FUNCTION_ARGS)
|
|||||||
memcpy(str, VARDATA(string), len);
|
memcpy(str, VARDATA(string), len);
|
||||||
*(str + len) = '\0';
|
*(str + len) = '\0';
|
||||||
|
|
||||||
result = DatumGetObjectId(DirectFunctionCall1(oidin,
|
result = oidin_subr("text_oid", str, NULL);
|
||||||
CStringGetDatum(str)));
|
|
||||||
pfree(str);
|
pfree(str);
|
||||||
|
|
||||||
PG_RETURN_OID(result);
|
PG_RETURN_OID(result);
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
* use header files that are otherwise internal to Postgres to interface
|
* use header files that are otherwise internal to Postgres to interface
|
||||||
* with the backend.
|
* 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
|
#ifndef POSTGRES_EXT_H
|
||||||
#define POSTGRES_EXT_H
|
#define POSTGRES_EXT_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Object ID is a fundamental type in Postgres.
|
||||||
|
*/
|
||||||
typedef unsigned int Oid;
|
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.)
|
* attribute names, function names, etc.)
|
||||||
*
|
*
|
||||||
* NOTE that databases with different NAMEDATALEN's cannot interoperate!
|
* NOTE that databases with different NAMEDATALEN's cannot interoperate!
|
||||||
|
Loading…
x
Reference in New Issue
Block a user