@@ -6968,10 +6968,7 @@ set_var_from_str(const char *str, const char *cp,
6968
6968
}
6969
6969
6970
6970
if (!isdigit ((unsigned char ) * cp ))
6971
- ereturn (escontext , false,
6972
- (errcode (ERRCODE_INVALID_TEXT_REPRESENTATION ),
6973
- errmsg ("invalid input syntax for type %s: \"%s\"" ,
6974
- "numeric" , str )));
6971
+ goto invalid_syntax ;
6975
6972
6976
6973
decdigits = (unsigned char * ) palloc (strlen (cp ) + DEC_DIGITS * 2 );
6977
6974
@@ -6992,12 +6989,19 @@ set_var_from_str(const char *str, const char *cp,
6992
6989
else if (* cp == '.' )
6993
6990
{
6994
6991
if (have_dp )
6995
- ereturn (escontext , false,
6996
- (errcode (ERRCODE_INVALID_TEXT_REPRESENTATION ),
6997
- errmsg ("invalid input syntax for type %s: \"%s\"" ,
6998
- "numeric" , str )));
6992
+ goto invalid_syntax ;
6999
6993
have_dp = true;
7000
6994
cp ++ ;
6995
+ /* decimal point must not be followed by underscore */
6996
+ if (* cp == '_' )
6997
+ goto invalid_syntax ;
6998
+ }
6999
+ else if (* cp == '_' )
7000
+ {
7001
+ /* underscore must be followed by more digits */
7002
+ cp ++ ;
7003
+ if (!isdigit ((unsigned char ) * cp ))
7004
+ goto invalid_syntax ;
7001
7005
}
7002
7006
else
7003
7007
break ;
@@ -7010,17 +7014,8 @@ set_var_from_str(const char *str, const char *cp,
7010
7014
/* Handle exponent, if any */
7011
7015
if (* cp == 'e' || * cp == 'E' )
7012
7016
{
7013
- long exponent ;
7014
- char * endptr ;
7015
-
7016
- cp ++ ;
7017
- exponent = strtol (cp , & endptr , 10 );
7018
- if (endptr == cp )
7019
- ereturn (escontext , false,
7020
- (errcode (ERRCODE_INVALID_TEXT_REPRESENTATION ),
7021
- errmsg ("invalid input syntax for type %s: \"%s\"" ,
7022
- "numeric" , str )));
7023
- cp = endptr ;
7017
+ int64 exponent = 0 ;
7018
+ bool neg = false;
7024
7019
7025
7020
/*
7026
7021
* At this point, dweight and dscale can't be more than about
@@ -7030,10 +7025,43 @@ set_var_from_str(const char *str, const char *cp,
7030
7025
* fit in storage format, make_result() will complain about it later;
7031
7026
* for consistency use the same ereport errcode/text as make_result().
7032
7027
*/
7033
- if (exponent >= INT_MAX / 2 || exponent <= - (INT_MAX / 2 ))
7034
- ereturn (escontext , false,
7035
- (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
7036
- errmsg ("value overflows numeric format" )));
7028
+
7029
+ /* exponent sign */
7030
+ cp ++ ;
7031
+ if (* cp == '+' )
7032
+ cp ++ ;
7033
+ else if (* cp == '-' )
7034
+ {
7035
+ neg = true;
7036
+ cp ++ ;
7037
+ }
7038
+
7039
+ /* exponent digits */
7040
+ if (!isdigit ((unsigned char ) * cp ))
7041
+ goto invalid_syntax ;
7042
+
7043
+ while (* cp )
7044
+ {
7045
+ if (isdigit ((unsigned char ) * cp ))
7046
+ {
7047
+ exponent = exponent * 10 + (* cp ++ - '0' );
7048
+ if (exponent > PG_INT32_MAX / 2 )
7049
+ goto out_of_range ;
7050
+ }
7051
+ else if (* cp == '_' )
7052
+ {
7053
+ /* underscore must be followed by more digits */
7054
+ cp ++ ;
7055
+ if (!isdigit ((unsigned char ) * cp ))
7056
+ goto invalid_syntax ;
7057
+ }
7058
+ else
7059
+ break ;
7060
+ }
7061
+
7062
+ if (neg )
7063
+ exponent = - exponent ;
7064
+
7037
7065
dweight += (int ) exponent ;
7038
7066
dscale -= (int ) exponent ;
7039
7067
if (dscale < 0 )
@@ -7085,6 +7113,17 @@ set_var_from_str(const char *str, const char *cp,
7085
7113
* endptr = cp ;
7086
7114
7087
7115
return true;
7116
+
7117
+ out_of_range :
7118
+ ereturn (escontext , false,
7119
+ (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
7120
+ errmsg ("value overflows numeric format" )));
7121
+
7122
+ invalid_syntax :
7123
+ ereturn (escontext , false,
7124
+ (errcode (ERRCODE_INVALID_TEXT_REPRESENTATION ),
7125
+ errmsg ("invalid input syntax for type %s: \"%s\"" ,
7126
+ "numeric" , str )));
7088
7127
}
7089
7128
7090
7129
@@ -7167,6 +7206,13 @@ set_var_from_non_decimal_integer_str(const char *str, const char *cp, int sign,
7167
7206
tmp = tmp * 16 + xdigit_value (* cp ++ );
7168
7207
mul = mul * 16 ;
7169
7208
}
7209
+ else if (* cp == '_' )
7210
+ {
7211
+ /* Underscore must be followed by more digits */
7212
+ cp ++ ;
7213
+ if (!isxdigit ((unsigned char ) * cp ))
7214
+ goto invalid_syntax ;
7215
+ }
7170
7216
else
7171
7217
break ;
7172
7218
}
@@ -7197,6 +7243,13 @@ set_var_from_non_decimal_integer_str(const char *str, const char *cp, int sign,
7197
7243
tmp = tmp * 8 + (* cp ++ - '0' );
7198
7244
mul = mul * 8 ;
7199
7245
}
7246
+ else if (* cp == '_' )
7247
+ {
7248
+ /* Underscore must be followed by more digits */
7249
+ cp ++ ;
7250
+ if (* cp < '0' || * cp > '7' )
7251
+ goto invalid_syntax ;
7252
+ }
7200
7253
else
7201
7254
break ;
7202
7255
}
@@ -7227,6 +7280,13 @@ set_var_from_non_decimal_integer_str(const char *str, const char *cp, int sign,
7227
7280
tmp = tmp * 2 + (* cp ++ - '0' );
7228
7281
mul = mul * 2 ;
7229
7282
}
7283
+ else if (* cp == '_' )
7284
+ {
7285
+ /* Underscore must be followed by more digits */
7286
+ cp ++ ;
7287
+ if (* cp < '0' || * cp > '1' )
7288
+ goto invalid_syntax ;
7289
+ }
7230
7290
else
7231
7291
break ;
7232
7292
}
0 commit comments