mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 20:43:02 +01:00
Fixed use of very long DECFLOAT literals
This commit is contained in:
parent
529ef3d4f0
commit
5302ee1fdd
@ -179,3 +179,7 @@ DECFLOAT (FB 4.0)
|
|||||||
but poor precision) or scaled integers (good support for further processing and
|
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
|
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.
|
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.
|
||||||
|
|
||||||
|
@ -2103,8 +2103,13 @@ void CVT_make_null_string(const dsc* desc,
|
|||||||
|
|
||||||
if (*address != temp->vary_string)
|
if (*address != temp->vary_string)
|
||||||
{
|
{
|
||||||
|
length -= sizeof(USHORT); // Take into an account VaryStr specifics
|
||||||
if (len > length)
|
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);
|
memcpy(temp->vary_string, *address, len);
|
||||||
temp->vary_length = 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).
|
* 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;
|
Decimal64 d64;
|
||||||
|
|
||||||
// adjust exact numeric values to same scaling
|
// 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).
|
* 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;
|
Decimal128 d128;
|
||||||
|
|
||||||
// adjust exact numeric values to same scaling
|
// adjust exact numeric values to same scaling
|
||||||
|
@ -6797,7 +6797,7 @@ DmlNode* LiteralNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch*
|
|||||||
|
|
||||||
l = csb->csb_blr_reader.getWord();
|
l = csb->csb_blr_reader.getWord();
|
||||||
q = csb->csb_blr_reader.getPos();
|
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;
|
node->litDesc.dsc_dtype = dtype;
|
||||||
|
|
||||||
switch (dtype)
|
switch (dtype)
|
||||||
@ -6881,8 +6881,9 @@ void LiteralNode::genConstant(DsqlCompilerScratch* dsqlScratch, const dsc* desc,
|
|||||||
// which is transmitted to the engine as a string.
|
// which is transmitted to the engine as a string.
|
||||||
|
|
||||||
GEN_descriptor(dsqlScratch, desc, true);
|
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)
|
if (negateValue)
|
||||||
{
|
{
|
||||||
|
@ -941,7 +941,7 @@ int Parser::yylexAux()
|
|||||||
FB_UINT64 number = 0;
|
FB_UINT64 number = 0;
|
||||||
FB_UINT64 expVal = 0;
|
FB_UINT64 expVal = 0;
|
||||||
FB_UINT64 limit_by_10 = MAX_SINT64 / 10;
|
FB_UINT64 limit_by_10 = MAX_SINT64 / 10;
|
||||||
SCHAR scale = 0;
|
int scale = 0;
|
||||||
|
|
||||||
for (--lex.ptr; lex.ptr < lex.end; lex.ptr++)
|
for (--lex.ptr; lex.ptr < lex.end; lex.ptr++)
|
||||||
{
|
{
|
||||||
@ -1030,6 +1030,9 @@ int Parser::yylexAux()
|
|||||||
{
|
{
|
||||||
fb_assert(have_digit);
|
fb_assert(have_digit);
|
||||||
|
|
||||||
|
if (scale < MIN_SCHAR || scale > MAX_SCHAR)
|
||||||
|
have_overflow = true;
|
||||||
|
|
||||||
if (have_exp_digit || have_overflow)
|
if (have_exp_digit || have_overflow)
|
||||||
{
|
{
|
||||||
yylval.stringPtr = newString(
|
yylval.stringPtr = newString(
|
||||||
|
@ -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
|
// This is a numeric value which is transported to the engine as
|
||||||
// a string. The engine will convert it. Use dtype_double so that
|
// a string. The engine will convert it. Use dtype_double so that
|
||||||
// the engine can distinguish it from an actual string.
|
// the engine can distinguish it from an actual string.
|
||||||
// Note: Due to the size of dsc_scale we are limited to numeric
|
// Note: Due to the size of dsc_sub_type we are limited to numeric
|
||||||
// constants of less than 256 bytes.
|
// 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_dtype = numeric_flag == CONSTANT_DOUBLE ? dtype_double : dtype_dec128;
|
||||||
literal->litDesc.dsc_scale = static_cast<signed char>(strlen(str));
|
literal->litDesc.dsc_scale = 0;
|
||||||
literal->litDesc.dsc_sub_type = 0;
|
size_t l = strlen(str);
|
||||||
literal->litDesc.dsc_length = sizeof(double);
|
if (l > MAX_USHORT)
|
||||||
literal->litDesc.dsc_address = (UCHAR*) str;
|
{
|
||||||
literal->litDesc.dsc_ttype() = ttype_ascii;
|
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;
|
break;
|
||||||
|
|
||||||
case CONSTANT_DATE:
|
case CONSTANT_DATE:
|
||||||
|
@ -258,6 +258,9 @@ UCHAR CVT_get_numeric(const UCHAR* string, const USHORT length, SSHORT* scale, v
|
|||||||
if (!digit_seen)
|
if (!digit_seen)
|
||||||
CVT_conversion_error(&desc, ERR_post);
|
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
|
if ((!over) && ((p < end) || // there is an exponent
|
||||||
((value < 0) && (sign != -1)))) // MAX_SINT64+1 wrapped around
|
((value < 0) && (sign != -1)))) // MAX_SINT64+1 wrapped around
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user