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:
parent
529ef3d4f0
commit
5302ee1fdd
@ -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.
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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(
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user