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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy