Skip to content

Commit 965a3d6

Browse files
committed
Fix realfailN lexer rules to not make assumptions about input format.
The realfail1 and realfail2 backup-prevention rules always returned token type FCONST, ignoring the possibility that what we've scanned is more appropriately described as ICONST. I think that at the time that code was added, it might actually have been safe to not distinguish; but since we started allowing AS-less aliases in SELECT target lists, it's definitely legal to have a number immediately followed by an identifier. In the SELECT case, it seems there's no visible consequence because make_const() will change the type back to integer anyway. But I'm worried that there are other contexts, or will be in future, where it's more important to get the constant's type right. Hence, use process_integer_literal to correctly determine which token type to return. Arguably this is a bug fix, but given the lack of evidence of user-visible problems, I'll refrain from back-patching. Discussion: https://postgr.es/m/21364.1542136808@sss.pgh.pa.us
1 parent 4766bcd commit 965a3d6

File tree

3 files changed

+21
-22
lines changed

3 files changed

+21
-22
lines changed

src/backend/parser/scan.l

+9-9
Original file line numberDiff line numberDiff line change
@@ -1005,22 +1005,18 @@ other .
10051005
}
10061006
{realfail1} {
10071007
/*
1008-
* throw back the [Ee], and treat as {decimal}. Note
1009-
* that it is possible the input is actually {integer},
1010-
* but since this case will almost certainly lead to a
1011-
* syntax error anyway, we don't bother to distinguish.
1008+
* throw back the [Ee], and figure out whether what
1009+
* remains is an {integer} or {decimal}.
10121010
*/
10131011
yyless(yyleng - 1);
10141012
SET_YYLLOC();
1015-
yylval->str = pstrdup(yytext);
1016-
return FCONST;
1013+
return process_integer_literal(yytext, yylval);
10171014
}
10181015
{realfail2} {
10191016
/* throw back the [Ee][+-], and proceed as above */
10201017
yyless(yyleng - 2);
10211018
SET_YYLLOC();
1022-
yylval->str = pstrdup(yytext);
1023-
return FCONST;
1019+
return process_integer_literal(yytext, yylval);
10241020
}
10251021

10261022

@@ -1255,6 +1251,10 @@ litbufdup(core_yyscan_t yyscanner)
12551251
return new;
12561252
}
12571253

1254+
/*
1255+
* Process {integer}. Note this will also do the right thing with {decimal},
1256+
* ie digits and a decimal point.
1257+
*/
12581258
static int
12591259
process_integer_literal(const char *token, YYSTYPE *lval)
12601260
{
@@ -1265,7 +1265,7 @@ process_integer_literal(const char *token, YYSTYPE *lval)
12651265
val = strtoint(token, &endptr, 10);
12661266
if (*endptr != '\0' || errno == ERANGE)
12671267
{
1268-
/* integer too large, treat it as a float */
1268+
/* integer too large (or contains decimal pt), treat it as a float */
12691269
lval->str = pstrdup(token);
12701270
return FCONST;
12711271
}

src/fe_utils/psqlscan.l

+3-4
Original file line numberDiff line numberDiff line change
@@ -887,10 +887,9 @@ other .
887887
}
888888
{realfail1} {
889889
/*
890-
* throw back the [Ee], and treat as {decimal}. Note
891-
* that it is possible the input is actually {integer},
892-
* but since this case will almost certainly lead to a
893-
* syntax error anyway, we don't bother to distinguish.
890+
* throw back the [Ee], and figure out whether what
891+
* remains is an {integer} or {decimal}.
892+
* (in psql, we don't actually care...)
894893
*/
895894
yyless(yyleng - 1);
896895
ECHO;

src/interfaces/ecpg/preproc/pgc.l

+9-9
Original file line numberDiff line numberDiff line change
@@ -900,20 +900,16 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
900900
}
901901
{realfail1} {
902902
/*
903-
* throw back the [Ee], and treat as {decimal}. Note
904-
* that it is possible the input is actually {integer},
905-
* but since this case will almost certainly lead to a
906-
* syntax error anyway, we don't bother to distinguish.
903+
* throw back the [Ee], and figure out whether what
904+
* remains is an {integer} or {decimal}.
907905
*/
908906
yyless(yyleng - 1);
909-
base_yylval.str = mm_strdup(yytext);
910-
return FCONST;
907+
return process_integer_literal(yytext, &base_yylval);
911908
}
912909
{realfail2} {
913910
/* throw back the [Ee][+-], and proceed as above */
914911
yyless(yyleng - 2);
915-
base_yylval.str = mm_strdup(yytext);
916-
return FCONST;
912+
return process_integer_literal(yytext, &base_yylval);
917913
}
918914
} /* <C,SQL> */
919915

@@ -1473,6 +1469,10 @@ addlitchar(unsigned char ychar)
14731469
literalbuf[literallen] = '\0';
14741470
}
14751471

1472+
/*
1473+
* Process {integer}. Note this will also do the right thing with {decimal},
1474+
* ie digits and a decimal point.
1475+
*/
14761476
static int
14771477
process_integer_literal(const char *token, YYSTYPE *lval)
14781478
{
@@ -1483,7 +1483,7 @@ process_integer_literal(const char *token, YYSTYPE *lval)
14831483
val = strtoint(token, &endptr, 10);
14841484
if (*endptr != '\0' || errno == ERANGE)
14851485
{
1486-
/* integer too large, treat it as a float */
1486+
/* integer too large (or contains decimal pt), treat it as a float */
14871487
lval->str = mm_strdup(token);
14881488
return FCONST;
14891489
}

0 commit comments

Comments
 (0)