8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 04:03:04 +01:00

Fixed regression with numeric literal having value equal to MIN_SINT64

This commit is contained in:
Alex Peshkoff 2017-07-02 23:06:20 +03:00
parent a0d26e7684
commit 933bd49536
4 changed files with 78 additions and 16 deletions

View File

@ -939,6 +939,7 @@ int Parser::yylexAux()
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,18 +1011,20 @@ 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;
}
}
else if ( (('E' == c) || ('e' == c)) && have_digit )
have_exp = true;
else
@ -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)

View File

@ -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);

View File

@ -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

View File

@ -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