mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 00:43:02 +01:00
Fixed regression with numeric literal having value equal to MIN_SINT64
This commit is contained in:
parent
a0d26e7684
commit
933bd49536
@ -932,13 +932,14 @@ int Parser::yylexAux()
|
||||
{
|
||||
// The following variables are used to recognize kinds of numbers.
|
||||
|
||||
bool have_error = false; // syntax error or value too large
|
||||
bool have_digit = false; // we've seen a digit
|
||||
bool have_decimal = false; // we've seen a '.'
|
||||
bool have_exp = false; // digit ... [eE]
|
||||
bool have_exp_sign = false; // digit ... [eE] {+-]
|
||||
bool have_exp_digit = false; // digit ... [eE] ... digit
|
||||
bool have_overflow = false; // value of digits > MAX_SINT64
|
||||
bool have_error = false; // syntax error or value too large
|
||||
bool have_digit = false; // we've seen a digit
|
||||
bool have_decimal = false; // we've seen a '.'
|
||||
bool have_exp = false; // digit ... [eE]
|
||||
bool have_exp_sign = false; // digit ... [eE] {+-]
|
||||
bool have_exp_digit = false; // digit ... [eE] ... digit
|
||||
bool have_overflow = false; // value of digits > MAX_SINT64
|
||||
bool positive_overflow = false; // number is exactly (MAX_SINT64 + 1)
|
||||
FB_UINT64 number = 0;
|
||||
int expVal = 0;
|
||||
FB_UINT64 limit_by_10 = MAX_SINT64 / 10;
|
||||
@ -1010,17 +1011,19 @@ int Parser::yylexAux()
|
||||
if ((number > limit_by_10) || (c >= '8'))
|
||||
{
|
||||
have_overflow = true;
|
||||
if ((number == limit_by_10) && (c == '8'))
|
||||
positive_overflow = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
positive_overflow = false;
|
||||
|
||||
if (!have_overflow)
|
||||
{
|
||||
number = number * 10 + (c - '0');
|
||||
|
||||
if (have_decimal)
|
||||
--scale;
|
||||
}
|
||||
if (have_decimal)
|
||||
--scale;
|
||||
}
|
||||
else if ( (('E' == c) || ('e' == c)) && have_digit )
|
||||
have_exp = true;
|
||||
@ -1036,8 +1039,14 @@ int Parser::yylexAux()
|
||||
{
|
||||
fb_assert(have_digit);
|
||||
|
||||
if (positive_overflow)
|
||||
have_overflow = false;
|
||||
|
||||
if (scale < MIN_SCHAR || scale > MAX_SCHAR)
|
||||
{
|
||||
have_overflow = true;
|
||||
positive_overflow = false;
|
||||
}
|
||||
|
||||
// check for a more complex overflow case
|
||||
if ((!have_overflow) && (expSign > 0) && (expVal > -scale))
|
||||
@ -1045,19 +1054,33 @@ int Parser::yylexAux()
|
||||
expVal += scale;
|
||||
double maxNum = DBL_MAX / pow(10.0, expVal);
|
||||
if (double(number) > maxNum)
|
||||
{
|
||||
have_overflow = true;
|
||||
positive_overflow = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Should we use floating point type?
|
||||
if (have_exp_digit || have_overflow)
|
||||
if (have_exp_digit || have_overflow || positive_overflow)
|
||||
{
|
||||
if (positive_overflow && scale)
|
||||
{
|
||||
yylval.lim64ptr = newLim64String(
|
||||
Firebird::string(lex.last_token, lex.ptr - lex.last_token), scale);
|
||||
lex.last_token_bk = lex.last_token;
|
||||
lex.line_start_bk = lex.line_start;
|
||||
lex.lines_bk = lex.lines;
|
||||
|
||||
return TOK_LIMIT64_NUMBER;
|
||||
}
|
||||
|
||||
yylval.stringPtr = newString(
|
||||
Firebird::string(lex.last_token, lex.ptr - lex.last_token));
|
||||
lex.last_token_bk = lex.last_token;
|
||||
lex.line_start_bk = lex.line_start;
|
||||
lex.lines_bk = lex.lines;
|
||||
|
||||
return have_overflow ? TOK_DECIMAL_NUMBER : TOK_FLOAT_NUMBER;
|
||||
return positive_overflow ? TOK_LIMIT64_INT : have_overflow ? TOK_DECIMAL_NUMBER : TOK_FLOAT_NUMBER;
|
||||
}
|
||||
|
||||
if (!have_exp)
|
||||
|
@ -144,6 +144,11 @@ public:
|
||||
return FB_NEW_POOL(getPool()) Firebird::string(getPool(), s);
|
||||
}
|
||||
|
||||
Lim64String* newLim64String(const Firebird::string& s, int scale)
|
||||
{
|
||||
return FB_NEW_POOL(getPool()) Lim64String(getPool(), s, scale);
|
||||
}
|
||||
|
||||
IntlString* newIntlString(const Firebird::string& s, const char* charSet = NULL)
|
||||
{
|
||||
return FB_NEW_POOL(getPool()) IntlString(getPool(), s, charSet);
|
||||
|
@ -983,6 +983,23 @@ private:
|
||||
Firebird::string s;
|
||||
};
|
||||
|
||||
class Lim64String : public Firebird::string
|
||||
{
|
||||
public:
|
||||
Lim64String(Firebird::MemoryPool& p, const Firebird::string& str, int sc)
|
||||
: Firebird::string(p, str),
|
||||
scale(sc)
|
||||
{ }
|
||||
|
||||
int getScale()
|
||||
{
|
||||
return scale;
|
||||
}
|
||||
|
||||
private:
|
||||
int scale;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
/*! \var unsigned DSQL_debug
|
||||
|
@ -332,8 +332,8 @@ using namespace Firebird;
|
||||
%token <metaNamePtr> WORK
|
||||
%token <metaNamePtr> WRITE
|
||||
|
||||
%token <stringPtr> FLOAT_NUMBER
|
||||
%token <stringPtr> DECIMAL_NUMBER
|
||||
%token <stringPtr> FLOAT_NUMBER DECIMAL_NUMBER LIMIT64_INT
|
||||
%token <lim64ptr> LIMIT64_NUMBER
|
||||
%token <metaNamePtr> SYMBOL
|
||||
%token <int32Val> NUMBER
|
||||
|
||||
@ -681,6 +681,7 @@ using namespace Firebird;
|
||||
Firebird::QualifiedName* qualifiedNamePtr;
|
||||
Firebird::string* stringPtr;
|
||||
Jrd::IntlString* intlStringPtr;
|
||||
Jrd::Lim64String* lim64ptr;
|
||||
Jrd::DbFileClause* dbFileClause;
|
||||
Firebird::Array<NestConst<Jrd::DbFileClause> >* dbFilesClause;
|
||||
Jrd::ExternalClause* externalClause;
|
||||
@ -1846,6 +1847,10 @@ sequence_value
|
||||
|
||||
$$ = -signedNumber;
|
||||
}
|
||||
| '-' LIMIT64_INT
|
||||
{
|
||||
$$ = MIN_SINT64;
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
@ -7118,12 +7123,24 @@ value_list
|
||||
%type <valueExprNode> constant
|
||||
constant
|
||||
: u_constant
|
||||
| '-' u_numeric_constant { $$ = newNode<NegateNode>($2); }
|
||||
| '-' ul_numeric_constant { $$ = newNode<NegateNode>($2); }
|
||||
| '-' LIMIT64_INT { $$ = MAKE_const_sint64(MIN_SINT64, 0); }
|
||||
| '-' LIMIT64_NUMBER { $$ = MAKE_const_sint64(MIN_SINT64, $2->getScale()); }
|
||||
| boolean_literal
|
||||
;
|
||||
|
||||
%type <valueExprNode> u_numeric_constant
|
||||
u_numeric_constant
|
||||
: ul_numeric_constant
|
||||
{ $$ = $1; }
|
||||
| LIMIT64_NUMBER
|
||||
{ $$ = MAKE_constant($1->c_str(), CONSTANT_DECIMAL); }
|
||||
| LIMIT64_INT
|
||||
{ $$ = MAKE_constant($1->c_str(), CONSTANT_DECIMAL); }
|
||||
;
|
||||
|
||||
%type <valueExprNode> ul_numeric_constant
|
||||
ul_numeric_constant
|
||||
: NUMBER
|
||||
{ $$ = MAKE_const_slong($1); }
|
||||
| FLOAT_NUMBER
|
||||
|
Loading…
Reference in New Issue
Block a user