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

Fixed use of very long DECFLOAT literals

This commit is contained in:
AlexPeshkoff 2017-05-03 19:58:56 +03:00
parent 529ef3d4f0
commit 5302ee1fdd
6 changed files with 37 additions and 16 deletions

View File

@ -179,3 +179,7 @@ DECFLOAT (FB 4.0)
but poor precision) or scaled integers (good support for further processing and
required precision but range of values is very limited). When using is a tool like
generic purporse GUI client choice of CHAR binding is OK in most cases.
4. Although length of DECFLOAT(34) literal can exceed 6000 bytes (0.000<6000 zeros>00123)
implementation limit exists - length of such literal should not exceed 1024 bytes.

View File

@ -2103,8 +2103,13 @@ void CVT_make_null_string(const dsc* desc,
if (*address != temp->vary_string)
{
length -= sizeof(USHORT); // Take into an account VaryStr specifics
if (len > length)
len = length;
{
err(Arg::Gds(isc_arith_except) << Arg::Gds(isc_string_truncation) <<
Arg::Gds(isc_imp_exc) <<
Arg::Gds(isc_trunc_limits) << Arg::Num(length) << Arg::Num(len));
}
memcpy(temp->vary_string, *address, len);
temp->vary_length = len;
}
@ -2534,7 +2539,7 @@ Decimal64 CVT_get_dec64(const dsc* desc, DecimalStatus decSt, ErrorFunction err)
* Convert something arbitrary to a DecFloat(16) / (64 bit).
*
**************************************/
VaryStr<50> buffer; // long enough to represent largest decimal float in ASCII
VaryStr<512> buffer; // long enough to represent largest decimal float in ASCII
Decimal64 d64;
// adjust exact numeric values to same scaling
@ -2618,7 +2623,7 @@ Decimal128 CVT_get_dec128(const dsc* desc, DecimalStatus decSt, ErrorFunction er
* Convert something arbitrary to a DecFloat(34) / (128 bit).
*
**************************************/
VaryStr<50> buffer; // long enough to represent largest decimal float in ASCII
VaryStr<1024> buffer; // represents unreasonably long decfloat literal in ASCII
Decimal128 d128;
// adjust exact numeric values to same scaling

View File

@ -6797,7 +6797,7 @@ DmlNode* LiteralNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch*
l = csb->csb_blr_reader.getWord();
q = csb->csb_blr_reader.getPos();
dtype = CVT_get_numeric(q, l, &scale, p); // use decfloat to pass literal ???
dtype = CVT_get_numeric(q, l, &scale, p);
node->litDesc.dsc_dtype = dtype;
switch (dtype)
@ -6881,8 +6881,9 @@ void LiteralNode::genConstant(DsqlCompilerScratch* dsqlScratch, const dsc* desc,
// which is transmitted to the engine as a string.
GEN_descriptor(dsqlScratch, desc, true);
// Length of string literal, cast because it could be > 127 bytes.
const USHORT l = (USHORT)(UCHAR) desc->dsc_scale;
// Length of string literal
const USHORT l = desc->dsc_length;
if (negateValue)
{

View File

@ -941,7 +941,7 @@ int Parser::yylexAux()
FB_UINT64 number = 0;
FB_UINT64 expVal = 0;
FB_UINT64 limit_by_10 = MAX_SINT64 / 10;
SCHAR scale = 0;
int scale = 0;
for (--lex.ptr; lex.ptr < lex.end; lex.ptr++)
{
@ -1030,6 +1030,9 @@ int Parser::yylexAux()
{
fb_assert(have_digit);
if (scale < MIN_SCHAR || scale > MAX_SCHAR)
have_overflow = true;
if (have_exp_digit || have_overflow)
{
yylval.stringPtr = newString(

View File

@ -122,16 +122,21 @@ ValueExprNode* MAKE_constant(const char* str, dsql_constant_type numeric_flag)
// This is a numeric value which is transported to the engine as
// a string. The engine will convert it. Use dtype_double so that
// the engine can distinguish it from an actual string.
// Note: Due to the size of dsc_scale we are limited to numeric
// constants of less than 256 bytes.
// Note: Due to the size of dsc_sub_type we are limited to numeric
// constants of less than 64K - 1 bytes.
literal->litDesc.dsc_dtype = numeric_flag == CONSTANT_DOUBLE ? dtype_double : dtype_dec128;
// Scale has no use for double
literal->litDesc.dsc_scale = static_cast<signed char>(strlen(str));
literal->litDesc.dsc_sub_type = 0;
literal->litDesc.dsc_length = sizeof(double);
literal->litDesc.dsc_address = (UCHAR*) str;
literal->litDesc.dsc_ttype() = ttype_ascii;
{
literal->litDesc.dsc_dtype = numeric_flag == CONSTANT_DOUBLE ? dtype_double : dtype_dec128;
literal->litDesc.dsc_scale = 0;
size_t l = strlen(str);
if (l > MAX_USHORT)
{
ERRD_post(Arg::Gds(isc_imp_exc) << Arg::Gds(isc_random) << "Numeric literal too long");
}
literal->litDesc.dsc_length = static_cast<SSHORT>(l);
literal->litDesc.dsc_address = (UCHAR*) str;
literal->litDesc.dsc_ttype() = ttype_ascii;
}
break;
case CONSTANT_DATE:

View File

@ -258,6 +258,9 @@ UCHAR CVT_get_numeric(const UCHAR* string, const USHORT length, SSHORT* scale, v
if (!digit_seen)
CVT_conversion_error(&desc, ERR_post);
if ((local_scale > MAX_SCHAR) || (local_scale < MIN_SCHAR))
over = true;
if ((!over) && ((p < end) || // there is an exponent
((value < 0) && (sign != -1)))) // MAX_SINT64+1 wrapped around
{