Commit b32cac80 authored by Tom Lane's avatar Tom Lane

Fix Joubert's complaint that int8-sized numeric literals are mishandled

on Alpha (because parser mistakenly assumes that a nonoverflow result
from strtol means the value will fit into int4).  A scan for other uses
of strtol and strtoul found a couple other places with the same mistake;
fix them too.  The changes are all conditional on HAVE_LONG_INT_64 to
avoid complaints from compilers that think x != x is a silly test
(cf. pg_atoi).
parent 339cd6b9
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/read.c,v 1.29 2001/03/22 03:59:32 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/nodes/read.c,v 1.30 2001/03/22 17:41:47 tgl Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -203,7 +203,6 @@ nodeTokenType(char *token, int length) ...@@ -203,7 +203,6 @@ nodeTokenType(char *token, int length)
NodeTag retval; NodeTag retval;
char *numptr; char *numptr;
int numlen; int numlen;
char *endptr;
/* /*
* Check if the token is a number * Check if the token is a number
...@@ -215,16 +214,23 @@ nodeTokenType(char *token, int length) ...@@ -215,16 +214,23 @@ nodeTokenType(char *token, int length)
if ((numlen > 0 && isdigit((unsigned char) *numptr)) || if ((numlen > 0 && isdigit((unsigned char) *numptr)) ||
(numlen > 1 && *numptr == '.' && isdigit((unsigned char) numptr[1]))) (numlen > 1 && *numptr == '.' && isdigit((unsigned char) numptr[1])))
{ {
/* /*
* Yes. Figure out whether it is integral or float; this requires * Yes. Figure out whether it is integral or float; this requires
* both a syntax check and a range check. strtol() can do both for * both a syntax check and a range check. strtol() can do both for
* us. We know the token will end at a character that strtol will * us. We know the token will end at a character that strtol will
* stop at, so we do not need to modify the string. * stop at, so we do not need to modify the string.
*/ */
long val;
char *endptr;
errno = 0; errno = 0;
(void) strtol(token, &endptr, 10); val = strtol(token, &endptr, 10);
if (endptr != token + length || errno == ERANGE) if (endptr != token + length || errno == ERANGE
#ifdef HAVE_LONG_INT_64
/* if long > 32 bits, check for overflow of int4 */
|| val != (long) ((int32) val)
#endif
)
return T_Float; return T_Float;
return T_Integer; return T_Integer;
} }
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/scan.l,v 1.87 2001/02/21 18:53:47 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/scan.l,v 1.88 2001/03/22 17:41:47 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -310,14 +310,21 @@ other . ...@@ -310,14 +310,21 @@ other .
startlit(); startlit();
} }
<xh>{xhstop} { <xh>{xhstop} {
long val;
char* endptr; char* endptr;
BEGIN(INITIAL); BEGIN(INITIAL);
errno = 0; errno = 0;
yylval.ival = strtol(literalbuf, &endptr, 16); val = strtol(literalbuf, &endptr, 16);
if (*endptr != '\0' || errno == ERANGE) if (*endptr != '\0' || errno == ERANGE
#ifdef HAVE_LONG_INT_64
/* if long > 32 bits, check for overflow of int4 */
|| val != (long) ((int32) val)
#endif
)
elog(ERROR, "Bad hexadecimal integer input '%s'", elog(ERROR, "Bad hexadecimal integer input '%s'",
literalbuf); literalbuf);
yylval.ival = val;
return ICONST; return ICONST;
} }
<xh><<EOF>> { elog(ERROR, "Unterminated hexadecimal integer"); } <xh><<EOF>> { elog(ERROR, "Unterminated hexadecimal integer"); }
...@@ -454,16 +461,23 @@ other . ...@@ -454,16 +461,23 @@ other .
} }
{integer} { {integer} {
long val;
char* endptr; char* endptr;
errno = 0; errno = 0;
yylval.ival = strtol((char *)yytext, &endptr, 10); val = strtol((char *)yytext, &endptr, 10);
if (*endptr != '\0' || errno == ERANGE) if (*endptr != '\0' || errno == ERANGE
#ifdef HAVE_LONG_INT_64
/* if long > 32 bits, check for overflow of int4 */
|| val != (long) ((int32) val)
#endif
)
{ {
/* integer too large, treat it as a float */ /* integer too large, treat it as a float */
yylval.str = pstrdup((char*)yytext); yylval.str = pstrdup((char*)yytext);
return FCONST; return FCONST;
} }
yylval.ival = val;
return ICONST; return ICONST;
} }
{decimal} { {decimal} {
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* Support for grand unified configuration scheme, including SET * Support for grand unified configuration scheme, including SET
* command, configuration file, and command line options. * command, configuration file, and command line options.
* *
* $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.34 2001/03/22 04:00:06 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.35 2001/03/22 17:41:47 tgl Exp $
* *
* Copyright 2000 by PostgreSQL Global Development Group * Copyright 2000 by PostgreSQL Global Development Group
* Written by Peter Eisentraut <peter_e@gmx.net>. * Written by Peter Eisentraut <peter_e@gmx.net>.
...@@ -520,7 +520,12 @@ parse_int(const char *value, int *result) ...@@ -520,7 +520,12 @@ parse_int(const char *value, int *result)
errno = 0; errno = 0;
val = strtol(value, &endptr, 0); val = strtol(value, &endptr, 0);
if (endptr == value || *endptr != '\0' || errno == ERANGE) if (endptr == value || *endptr != '\0' || errno == ERANGE
#ifdef HAVE_LONG_INT_64
/* if long > 32 bits, check for overflow of int4 */
|| val != (long) ((int32) val)
#endif
)
return false; return false;
if (result) if (result)
*result = (int) val; *result = (int) val;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment