mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-02-02 10:40:38 +01:00
Fixed #7997: Unexpected results when comparing integer with string containing integer value out of bigint range
(cherry picked from commit 7531251a05
)
This commit is contained in:
parent
728f8ee29e
commit
39406410e7
@ -2502,7 +2502,8 @@ static void hex_to_value(const char*& string, const char* end, RetPtr* retValue)
|
||||
static SSHORT cvt_decompose(const char* string,
|
||||
USHORT length,
|
||||
RetPtr* return_value,
|
||||
ErrorFunction err)
|
||||
ErrorFunction err,
|
||||
int* overflow = nullptr)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -2600,15 +2601,23 @@ static SSHORT cvt_decompose(const char* string,
|
||||
if (p >= end)
|
||||
continue;
|
||||
}
|
||||
err(Arg::Gds(isc_arith_except) << Arg::Gds(isc_numeric_out_of_range));
|
||||
if (overflow)
|
||||
*overflow = 1;
|
||||
else
|
||||
err(Arg::Gds(isc_arith_except) << Arg::Gds(isc_numeric_out_of_range));
|
||||
return 0;
|
||||
|
||||
case RetPtr::RETVAL_POSSIBLE_OVERFLOW:
|
||||
if ((*p > '8' && sign == -1) || (*p > '7' && sign != -1))
|
||||
{
|
||||
err(Arg::Gds(isc_arith_except) << Arg::Gds(isc_numeric_out_of_range));
|
||||
if (overflow)
|
||||
*overflow = 1;
|
||||
else
|
||||
err(Arg::Gds(isc_arith_except) << Arg::Gds(isc_numeric_out_of_range));
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -2758,9 +2767,9 @@ public:
|
||||
|
||||
lb10 compareLimitBy10()
|
||||
{
|
||||
if (value > Traits::UPPER_LIMIT_BY_10)
|
||||
if (static_cast<typename Traits::UnsignedType>(value) > Traits::UPPER_LIMIT_BY_10)
|
||||
return RETVAL_OVERFLOW;
|
||||
if (value == Traits::UPPER_LIMIT_BY_10)
|
||||
if (static_cast<typename Traits::UnsignedType>(value) == Traits::UPPER_LIMIT_BY_10)
|
||||
return RETVAL_POSSIBLE_OVERFLOW;
|
||||
return RETVAL_NO_OVERFLOW;
|
||||
}
|
||||
@ -2791,7 +2800,8 @@ class SSHORTTraits
|
||||
{
|
||||
public:
|
||||
typedef SSHORT ValueType;
|
||||
static const SSHORT UPPER_LIMIT_BY_10 = MAX_SSHORT / 10;
|
||||
typedef USHORT UnsignedType;
|
||||
static const USHORT UPPER_LIMIT_BY_10 = MAX_SSHORT / 10;
|
||||
static const SSHORT LOWER_LIMIT = MIN_SSHORT;
|
||||
};
|
||||
|
||||
@ -2818,7 +2828,8 @@ class SLONGTraits
|
||||
{
|
||||
public:
|
||||
typedef SLONG ValueType;
|
||||
static const SLONG UPPER_LIMIT_BY_10 = MAX_SLONG / 10;
|
||||
typedef ULONG UnsignedType;
|
||||
static const ULONG UPPER_LIMIT_BY_10 = MAX_SLONG / 10;
|
||||
static const SLONG LOWER_LIMIT = MIN_SLONG;
|
||||
};
|
||||
|
||||
@ -2845,11 +2856,12 @@ class SINT64Traits
|
||||
{
|
||||
public:
|
||||
typedef SINT64 ValueType;
|
||||
static const SINT64 UPPER_LIMIT_BY_10 = MAX_SINT64 / 10;
|
||||
typedef FB_UINT64 UnsignedType;
|
||||
static const FB_UINT64 UPPER_LIMIT_BY_10 = MAX_SINT64 / 10;
|
||||
static const SINT64 LOWER_LIMIT = MIN_SINT64;
|
||||
};
|
||||
|
||||
SSHORT CVT_decompose(const char* str, USHORT len, SINT64* val, ErrorFunction err)
|
||||
SSHORT CVT_decompose(const char* str, USHORT len, SINT64* val, ErrorFunction err, int* overflow)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -2864,7 +2876,7 @@ SSHORT CVT_decompose(const char* str, USHORT len, SINT64* val, ErrorFunction err
|
||||
**************************************/
|
||||
|
||||
RetValue<SINT64Traits> value(val);
|
||||
return cvt_decompose(str, len, &value, err);
|
||||
return cvt_decompose(str, len, &value, err, overflow);
|
||||
}
|
||||
|
||||
|
||||
@ -2872,6 +2884,7 @@ class I128Traits
|
||||
{
|
||||
public:
|
||||
typedef Int128 ValueType;
|
||||
typedef Int128 UnsignedType; // To be fixed when adding int256
|
||||
static const CInt128 UPPER_LIMIT_BY_10;
|
||||
static const CInt128 LOWER_LIMIT;
|
||||
};
|
||||
@ -3457,7 +3470,7 @@ SQUAD CVT_get_quad(const dsc* desc, SSHORT scale, DecimalStatus decSt, ErrorFunc
|
||||
}
|
||||
|
||||
|
||||
SINT64 CVT_get_int64(const dsc* desc, SSHORT scale, DecimalStatus decSt, ErrorFunction err)
|
||||
SINT64 CVT_get_int64(const dsc* desc, SSHORT scale, DecimalStatus decSt, ErrorFunction err, int* overflow)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -3559,7 +3572,7 @@ SINT64 CVT_get_int64(const dsc* desc, SSHORT scale, DecimalStatus decSt, ErrorFu
|
||||
{
|
||||
USHORT length =
|
||||
CVT_make_string(desc, ttype_ascii, &p, &buffer, sizeof(buffer), decSt, err);
|
||||
scale -= CVT_decompose(p, length, &value, err);
|
||||
scale -= CVT_decompose(p, length, &value, err, overflow);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -99,11 +99,11 @@ void CVT_move_common(const dsc*, dsc*, Firebird::DecimalStatus, Firebird::Callba
|
||||
void CVT_move(const dsc*, dsc*, Firebird::DecimalStatus, ErrorFunction);
|
||||
SSHORT CVT_decompose(const char*, USHORT, SSHORT*, ErrorFunction);
|
||||
SSHORT CVT_decompose(const char*, USHORT, SLONG*, ErrorFunction);
|
||||
SSHORT CVT_decompose(const char*, USHORT, SINT64*, ErrorFunction);
|
||||
SSHORT CVT_decompose(const char*, USHORT, SINT64*, ErrorFunction, int* overflow = nullptr);
|
||||
SSHORT CVT_decompose(const char*, USHORT, Firebird::Int128*, ErrorFunction);
|
||||
USHORT CVT_get_string_ptr(const dsc*, USHORT*, UCHAR**, vary*, USHORT, Firebird::DecimalStatus, ErrorFunction);
|
||||
USHORT CVT_get_string_ptr_common(const dsc*, USHORT*, UCHAR**, vary*, USHORT, Firebird::DecimalStatus, Firebird::Callbacks*);
|
||||
SINT64 CVT_get_int64(const dsc*, SSHORT, Firebird::DecimalStatus, ErrorFunction);
|
||||
SINT64 CVT_get_int64(const dsc*, SSHORT, Firebird::DecimalStatus, ErrorFunction, int* overflow = nullptr);
|
||||
SQUAD CVT_get_quad(const dsc*, SSHORT, Firebird::DecimalStatus, ErrorFunction);
|
||||
void CVT_string_to_datetime(const dsc*, ISC_TIMESTAMP_TZ*, bool*, const Firebird::EXPECT_DATETIME,
|
||||
bool, Firebird::Callbacks*);
|
||||
|
@ -236,10 +236,10 @@ UCHAR CVT_get_numeric(const UCHAR* string, const USHORT length, SSHORT* scale, v
|
||||
|
||||
if (!over)
|
||||
{
|
||||
if (value >= NUMERIC_LIMIT)
|
||||
if (static_cast<FB_UINT64>(value) >= NUMERIC_LIMIT)
|
||||
{
|
||||
// possibility of an overflow
|
||||
if ((value > NUMERIC_LIMIT) || (*p > '8' && sign == -1) || (*p > '7' && sign != -1))
|
||||
if ((static_cast<FB_UINT64>(value) > NUMERIC_LIMIT) || (*p > '8' && sign == -1) || (*p > '7' && sign != -1))
|
||||
over = true;
|
||||
}
|
||||
|
||||
|
@ -543,8 +543,18 @@ int CVT2_compare(const dsc* arg1, const dsc* arg2, Firebird::DecimalStatus decSt
|
||||
scale = MIN(arg1->dsc_scale, arg2->dsc_scale);
|
||||
else
|
||||
scale = arg1->dsc_scale;
|
||||
const SINT64 temp1 = CVT_get_int64(arg1, scale, decSt, ERR_post);
|
||||
const SINT64 temp2 = CVT_get_int64(arg2, scale, decSt, ERR_post);
|
||||
|
||||
int overflow = 0;
|
||||
const SINT64 temp1 = CVT_get_int64(arg1, scale, decSt, ERR_post, &overflow);
|
||||
const SINT64 temp2 = CVT_get_int64(arg2, scale, decSt, ERR_post, &overflow);
|
||||
|
||||
if (overflow)
|
||||
{
|
||||
const Int128 temp1 = CVT_get_int128(arg1, scale, decSt, ERR_post);
|
||||
const Int128 temp2 = CVT_get_int128(arg2, scale, decSt, ERR_post);
|
||||
return temp1.compare(temp2);
|
||||
}
|
||||
|
||||
if (temp1 == temp2)
|
||||
return 0;
|
||||
if (temp1 > temp2)
|
||||
|
Loading…
Reference in New Issue
Block a user