summaryrefslogtreecommitdiff
path: root/src/backend/utils/adt
diff options
context:
space:
mode:
authorNeil Conway <neilc@samurai.com>2004-03-11 02:11:14 +0000
committerNeil Conway <neilc@samurai.com>2004-03-11 02:11:14 +0000
commite2ded829f6b672529d072620e43de65466286b59 (patch)
tree9ffc21ade136f5e667fb41dbd2e8b1c56436b3e5 /src/backend/utils/adt
parent0b86ade1c2f3dcd2407e535baad1654e65252316 (diff)
downloadpostgresql-e2ded829f6b672529d072620e43de65466286b59.tar.gz
Revise int2/int4/int8/float4/float8 input routines to allow for
any amount of leading or trailing whitespace (where "whitespace" is defined by isspace()). This is for SQL conformance, as well as consistency with other numeric types (e.g. oid, numeric). Also refactor pg_atoi() to avoid looking at errno where not necessary, and add a bunch of regression tests for the input to these types.
Diffstat (limited to 'src/backend/utils/adt')
-rw-r--r--src/backend/utils/adt/float.c121
-rw-r--r--src/backend/utils/adt/int8.c9
-rw-r--r--src/backend/utils/adt/numutils.c31
-rw-r--r--src/backend/utils/adt/oid.c30
4 files changed, 115 insertions, 76 deletions
diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c
index f9c4894794..2707c83fd6 100644
--- a/src/backend/utils/adt/float.c
+++ b/src/backend/utils/adt/float.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/float.c,v 1.97 2004/03/04 21:47:18 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/float.c,v 1.98 2004/03/11 02:11:13 neilc Exp $
*
*-------------------------------------------------------------------------
*/
@@ -185,14 +185,37 @@ float4in(PG_FUNCTION_ARGS)
errno = 0;
val = strtod(num, &endptr);
- if (*endptr != '\0')
+
+ if (errno == ERANGE)
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("\"%s\" is out of range for type real", num)));
+
+ if (num == endptr)
{
/*
- * XXX we should accept "Infinity" and "-Infinity" too, but what
- * are the correct values to assign? HUGE_VAL will provoke an
- * error from CheckFloat4Val.
+ * We didn't find anything that looks like a float in the input
+ *
+ * In releases prior to 7.5, we accepted an empty string as
+ * valid input (yielding a float8 of 0). In 7.5, we accept
+ * empty strings, but emit a warning noting that the feature
+ * is deprecated. In 7.6+, the warning should be replaced by
+ * an error.
+ *
+ * XXX we should accept "Infinity" and "-Infinity" too, but
+ * what are the correct values to assign? HUGE_VAL will
+ * provoke an error from CheckFloat4Val.
*/
- if (strcasecmp(num, "NaN") == 0)
+ if (*num == '\0')
+ {
+ ereport(WARNING,
+ (errcode(ERRCODE_WARNING_DEPRECATED_FEATURE),
+ errmsg("deprecated input syntax for type real: \"\""),
+ errdetail("This input will be rejected in "
+ "a future release of PostgreSQL.")));
+ Assert(val == 0.0);
+ }
+ else if (strcasecmp(num, "NaN") == 0)
val = NAN;
else
ereport(ERROR,
@@ -200,26 +223,17 @@ float4in(PG_FUNCTION_ARGS)
errmsg("invalid input syntax for type real: \"%s\"",
num)));
}
- else
- {
- if (errno == ERANGE)
- ereport(ERROR,
- (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
- errmsg("\"%s\" is out of range for type real", num)));
- }
- /*
- * In releases prior to 7.5, we accepted an empty string as valid
- * input (yielding a float4 of 0). In 7.5, we accept empty
- * strings, but emit a warning noting that the feature is
- * deprecated. In 7.6+, the warning should be replaced by an error.
- */
- if (num == endptr)
- ereport(WARNING,
- (errcode(ERRCODE_WARNING_DEPRECATED_FEATURE),
- errmsg("deprecated input syntax for type real: \"\""),
- errdetail("This input will be rejected in "
- "a future release of PostgreSQL.")));
+ /* skip trailing whitespace */
+ while (*endptr != '\0' && isspace(*endptr))
+ endptr++;
+
+ /* if there is any junk left at the end of the string, bail out */
+ if (*endptr != '\0')
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ errmsg("invalid input syntax for type real: \"%s\"",
+ num)));
/*
* if we get here, we have a legal double, still need to check to see
@@ -300,9 +314,33 @@ float8in(PG_FUNCTION_ARGS)
errno = 0;
val = strtod(num, &endptr);
- if (*endptr != '\0')
+
+ if (errno == ERANGE)
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("\"%s\" is out of range for type double precision", num)));
+
+ if (num == endptr)
{
- if (strcasecmp(num, "NaN") == 0)
+ /*
+ * We didn't find anything that looks like a float in the input
+ *
+ * In releases prior to 7.5, we accepted an empty string as
+ * valid input (yielding a float8 of 0). In 7.5, we accept
+ * empty strings, but emit a warning noting that the feature
+ * is deprecated. In 7.6+, the warning should be replaced by
+ * an error.
+ */
+ if (*num == '\0')
+ {
+ ereport(WARNING,
+ (errcode(ERRCODE_WARNING_DEPRECATED_FEATURE),
+ errmsg("deprecated input syntax for type double precision: \"\""),
+ errdetail("This input will be rejected in "
+ "a future release of PostgreSQL.")));
+ Assert(val == 0.0);
+ }
+ else if (strcasecmp(num, "NaN") == 0)
val = NAN;
else if (strcasecmp(num, "Infinity") == 0)
val = HUGE_VAL;
@@ -314,26 +352,17 @@ float8in(PG_FUNCTION_ARGS)
errmsg("invalid input syntax for type double precision: \"%s\"",
num)));
}
- else
- {
- if (errno == ERANGE)
- ereport(ERROR,
- (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
- errmsg("\"%s\" is out of range for type double precision", num)));
- }
- /*
- * In releases prior to 7.5, we accepted an empty string as valid
- * input (yielding a float8 of 0). In 7.5, we accept empty
- * strings, but emit a warning noting that the feature is
- * deprecated. In 7.6+, the warning should be replaced by an error.
- */
- if (num == endptr)
- ereport(WARNING,
- (errcode(ERRCODE_WARNING_DEPRECATED_FEATURE),
- errmsg("deprecated input syntax for type double precision: \"\""),
- errdetail("This input will be rejected in "
- "a future release of PostgreSQL.")));
+ /* skip trailing whitespace */
+ while (*endptr != '\0' && isspace(*endptr))
+ endptr++;
+
+ /* if there is any junk left at the end of the string, bail out */
+ if (*endptr != '\0')
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ errmsg("invalid input syntax for type double precision: \"%s\"",
+ num)));
CheckFloat8Val(val);
diff --git a/src/backend/utils/adt/int8.c b/src/backend/utils/adt/int8.c
index 200876e798..8667e53680 100644
--- a/src/backend/utils/adt/int8.c
+++ b/src/backend/utils/adt/int8.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/int8.c,v 1.51 2004/02/03 08:29:56 joe Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/int8.c,v 1.52 2004/03/11 02:11:13 neilc Exp $
*
*-------------------------------------------------------------------------
*/
@@ -113,8 +113,11 @@ scanint8(const char *str, bool errorOK, int64 *result)
tmp = newtmp;
}
- /* trailing junk? */
- if (*ptr)
+ /* allow trailing whitespace, but not other trailing chars */
+ while (*ptr != '\0' && isspace(*ptr))
+ ptr++;
+
+ if (*ptr != '\0')
{
if (errorOK)
return false;
diff --git a/src/backend/utils/adt/numutils.c b/src/backend/utils/adt/numutils.c
index 20227884ed..17961017fa 100644
--- a/src/backend/utils/adt/numutils.c
+++ b/src/backend/utils/adt/numutils.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/numutils.c,v 1.61 2004/02/18 00:01:33 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/numutils.c,v 1.62 2004/03/11 02:11:13 neilc Exp $
*
*-------------------------------------------------------------------------
*/
@@ -19,6 +19,7 @@
#include <errno.h>
#include <math.h>
#include <limits.h>
+#include <ctype.h>
#include "utils/builtins.h"
@@ -45,10 +46,12 @@
/*
* pg_atoi: convert string to integer
*
- * size is the sizeof() the desired integral result (1, 2, or 4 bytes).
+ * 'size' is the sizeof() the desired integral result (1, 2, or 4 bytes).
*
- * c, if not 0, is the terminator character that may appear after the
- * integer. If 0, the string must end after the integer.
+ * allows any number of leading or trailing whitespace characters.
+ *
+ * 'c' is the character that terminates the input string (after any
+ * number of whitespace characters).
*
* Unlike plain atoi(), this will throw ereport() upon bad input format or
* overflow.
@@ -57,7 +60,7 @@ int32
pg_atoi(char *s, int size, int c)
{
long l;
- char *badp = NULL;
+ char *badp;
/*
* Some versions of strtol treat the empty string as an error, but
@@ -74,17 +77,21 @@ pg_atoi(char *s, int size, int c)
errno = 0;
l = strtol(s, &badp, 10);
- /*
- * strtol() 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 != ERANGE && errno != EINVAL)
+ /* We made no progress parsing the string, so bail out */
+ if (s == badp)
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for integer: \"%s\"",
s)));
- if (badp && *badp && *badp != c)
+
+ /*
+ * Skip any trailing whitespace; if anything but whitespace
+ * remains before the terminating character, bail out
+ */
+ while (*badp != c && isspace(*badp))
+ badp++;
+
+ if (*badp != c)
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for integer: \"%s\"",
diff --git a/src/backend/utils/adt/oid.c b/src/backend/utils/adt/oid.c
index 2119936d39..7ff6c6a27c 100644
--- a/src/backend/utils/adt/oid.c
+++ b/src/backend/utils/adt/oid.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/oid.c,v 1.55 2004/03/04 21:47:18 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/oid.c,v 1.56 2004/03/11 02:11:13 neilc Exp $
*
*-------------------------------------------------------------------------
*/
@@ -33,6 +33,19 @@ oidin_subr(const char *funcname, const char *s, char **endloc)
char *endptr;
Oid result;
+ /*
+ * In releases prior to 7.5, we accepted an empty string as valid
+ * input (yielding an OID of 0). In 7.5, we accept empty strings,
+ * but emit a warning noting that the feature is deprecated. In
+ * 7.6+, the warning should be replaced by an error.
+ */
+ if (*s == '\0')
+ ereport(WARNING,
+ (errcode(ERRCODE_WARNING_DEPRECATED_FEATURE),
+ errmsg("deprecated input syntax for type oid: \"\""),
+ errdetail("This input will be rejected in "
+ "a future release of PostgreSQL.")));
+
errno = 0;
cvt = strtoul(s, &endptr, 10);
@@ -47,20 +60,7 @@ oidin_subr(const char *funcname, const char *s, char **endloc)
errmsg("invalid input syntax for type oid: \"%s\"",
s)));
- /*
- * In releases prior to 7.5, we accepted an empty string as valid
- * input (yielding an OID of 0). In 7.5, we accept empty strings,
- * but emit a warning noting that the feature is deprecated. In
- * 7.6+, the warning should be replaced by an error.
- */
- if (*s == '\0')
- ereport(WARNING,
- (errcode(ERRCODE_WARNING_DEPRECATED_FEATURE),
- errmsg("deprecated input syntax for type oid: \"\""),
- errdetail("This input will be rejected in "
- "a future release of PostgreSQL.")));
-
- if (endptr == s && *s)
+ if (endptr == s && *s != '\0')
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for type oid: \"%s\"",