Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 0db1a95

Browse files
committed
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.
1 parent 369aace commit 0db1a95

File tree

2 files changed

+98
-54
lines changed

2 files changed

+98
-54
lines changed

src/backend/utils/adt/oid.c

Lines changed: 88 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,108 @@
11
/*-------------------------------------------------------------------------
22
*
33
* oid.c
4-
* Functions for the built-in type Oid.
4+
* Functions for the built-in type Oid ... also oidvector.
55
*
66
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/oid.c,v 1.41 2000/12/03 20:45:36 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/oid.c,v 1.42 2000/12/22 21:36:09 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
1515
#include "postgres.h"
1616

1717
#include <ctype.h>
1818
#include <errno.h>
19+
#include <limits.h>
1920

2021
#include "utils/builtins.h"
2122

2223
/*****************************************************************************
2324
* USER I/O ROUTINES *
2425
*****************************************************************************/
2526

27+
static Oid
28+
oidin_subr(const char *funcname, const char *s, char **endloc)
29+
{
30+
unsigned long cvt;
31+
char *endptr;
32+
Oid result;
33+
34+
errno = 0;
35+
36+
cvt = strtoul(s, &endptr, 10);
37+
38+
/*
39+
* strtoul() normally only sets ERANGE. On some systems it also
40+
* may set EINVAL, which simply means it couldn't parse the
41+
* input string. This is handled by the second "if" consistent
42+
* across platforms. Note that for historical reasons we accept
43+
* an empty string as meaning 0.
44+
*/
45+
if (errno && errno != EINVAL)
46+
elog(ERROR, "%s: error reading \"%s\": %m",
47+
funcname, s);
48+
if (endptr == s && *endptr)
49+
elog(ERROR, "%s: error in \"%s\": can't parse \"%s\"",
50+
funcname, s, endptr);
51+
52+
if (endloc)
53+
{
54+
/* caller wants to deal with rest of string */
55+
*endloc = endptr;
56+
}
57+
else
58+
{
59+
/* allow only whitespace after number */
60+
while (*endptr && isspace((unsigned char) *endptr))
61+
endptr++;
62+
if (*endptr)
63+
elog(ERROR, "%s: error in \"%s\": can't parse \"%s\"",
64+
funcname, s, endptr);
65+
}
66+
67+
result = (Oid) cvt;
68+
69+
/*
70+
* Cope with possibility that unsigned long is wider than Oid.
71+
*
72+
* To ensure consistent results on 32-bit and 64-bit platforms,
73+
* make sure the error message is the same as if strtoul() had
74+
* returned ERANGE.
75+
*/
76+
#if OID_MAX < ULONG_MAX
77+
if (cvt > (unsigned long) OID_MAX)
78+
elog(ERROR, "%s: error reading \"%s\": %s",
79+
funcname, s, strerror(ERANGE));
80+
#endif
81+
82+
return result;
83+
}
84+
85+
Datum
86+
oidin(PG_FUNCTION_ARGS)
87+
{
88+
char *s = PG_GETARG_CSTRING(0);
89+
Oid result;
90+
91+
result = oidin_subr("oidin", s, NULL);
92+
PG_RETURN_OID(result);
93+
}
94+
95+
Datum
96+
oidout(PG_FUNCTION_ARGS)
97+
{
98+
Oid o = PG_GETARG_OID(0);
99+
char *result = (char *) palloc(12);
100+
101+
snprintf(result, 12, "%u", o);
102+
PG_RETURN_CSTRING(result);
103+
}
104+
105+
26106
/*
27107
* oidvectorin - converts "num num ..." to internal form
28108
*
@@ -38,14 +118,13 @@ oidvectorin(PG_FUNCTION_ARGS)
38118

39119
result = (Oid *) palloc(sizeof(Oid[INDEX_MAX_KEYS]));
40120

41-
for (slot = 0; *oidString && slot < INDEX_MAX_KEYS; slot++)
121+
for (slot = 0; slot < INDEX_MAX_KEYS; slot++)
42122
{
43-
if (sscanf(oidString, "%u", &result[slot]) != 1)
44-
break;
45123
while (*oidString && isspace((unsigned char) *oidString))
46124
oidString++;
47-
while (*oidString && isdigit((unsigned char) *oidString))
48-
oidString++;
125+
if (*oidString == '\0')
126+
break;
127+
result[slot] = oidin_subr("oidvectorin", oidString, &oidString);
49128
}
50129
while (*oidString && isspace((unsigned char) *oidString))
51130
oidString++;
@@ -88,49 +167,6 @@ oidvectorout(PG_FUNCTION_ARGS)
88167
PG_RETURN_CSTRING(result);
89168
}
90169

91-
Datum
92-
oidin(PG_FUNCTION_ARGS)
93-
{
94-
char *s = PG_GETARG_CSTRING(0);
95-
unsigned long cvt;
96-
char *endptr;
97-
Oid result;
98-
99-
errno = 0;
100-
101-
cvt = strtoul(s, &endptr, 10);
102-
103-
/*
104-
* strtoul() normally only sets ERANGE. On some systems it also
105-
* may set EINVAL, which simply means it couldn't parse the
106-
* input string. This is handled by the second "if" consistent
107-
* across platforms.
108-
*/
109-
if (errno && errno != EINVAL)
110-
elog(ERROR, "oidin: error reading \"%s\": %m", s);
111-
if (endptr && *endptr)
112-
elog(ERROR, "oidin: error in \"%s\": can't parse \"%s\"", s, endptr);
113-
114-
/*
115-
* Cope with possibility that unsigned long is wider than Oid.
116-
*/
117-
result = (Oid) cvt;
118-
if ((unsigned long) result != cvt)
119-
elog(ERROR, "oidin: error reading \"%s\": value too large", s);
120-
121-
return ObjectIdGetDatum(result);
122-
}
123-
124-
Datum
125-
oidout(PG_FUNCTION_ARGS)
126-
{
127-
Oid o = PG_GETARG_OID(0);
128-
char *result = (char *) palloc(12);
129-
130-
snprintf(result, 12, "%u", o);
131-
PG_RETURN_CSTRING(result);
132-
}
133-
134170
/*****************************************************************************
135171
* PUBLIC ROUTINES *
136172
*****************************************************************************/
@@ -294,8 +330,8 @@ text_oid(PG_FUNCTION_ARGS)
294330
memcpy(str, VARDATA(string), len);
295331
*(str + len) = '\0';
296332

297-
result = DatumGetObjectId(DirectFunctionCall1(oidin,
298-
CStringGetDatum(str)));
333+
result = oidin_subr("text_oid", str, NULL);
334+
299335
pfree(str);
300336

301337
PG_RETURN_OID(result);

src/include/postgres_ext.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,25 @@
1616
* use header files that are otherwise internal to Postgres to interface
1717
* with the backend.
1818
*
19-
* $Id: postgres_ext.h,v 1.4 1999/06/04 21:12:07 tgl Exp $
19+
* $Id: postgres_ext.h,v 1.5 2000/12/22 21:36:09 tgl Exp $
2020
*
2121
*-------------------------------------------------------------------------
2222
*/
2323

2424
#ifndef POSTGRES_EXT_H
2525
#define POSTGRES_EXT_H
2626

27+
/*
28+
* Object ID is a fundamental type in Postgres.
29+
*/
2730
typedef unsigned int Oid;
2831

29-
/* NAMEDATALEN is the max length for system identifiers (e.g. table names,
32+
#define OID_MAX UINT_MAX
33+
/* you will need to include <limits.h> to use the above #define */
34+
35+
36+
/*
37+
* NAMEDATALEN is the max length for system identifiers (e.g. table names,
3038
* attribute names, function names, etc.)
3139
*
3240
* NOTE that databases with different NAMEDATALEN's cannot interoperate!

0 commit comments

Comments
 (0)