Do explicit range tests before attempting to convert a 64-bit float
into a 64-bit integer. Some systems (windows) seem to throw exceptions if the conversion is out of range. Ticket #2880. (CVS 4706) FossilOrigin-Name: 4744257d3cd2dd96485fde6d9f60542714383421
This commit is contained in:
parent
efe3d656b6
commit
d8c303fe0a
12
manifest
12
manifest
@ -1,5 +1,5 @@
|
||||
C Attempt\sto\swork\saround\sa\sbug\sin\sthe\sBorland\sBCC\s5.5.1\scompiler.\s\sTicket\s#2880.\s(CVS\s4705)
|
||||
D 2008-01-11T00:06:11
|
||||
C Do\sexplicit\srange\stests\sbefore\sattempting\sto\sconvert\sa\s64-bit\sfloat\ninto\sa\s64-bit\sinteger.\s\sSome\ssystems\s(windows)\sseem\sto\sthrow\sexceptions\nif\sthe\sconversion\sis\sout\sof\srange.\s\sTicket\s#2880.\s(CVS\s4706)
|
||||
D 2008-01-11T15:27:03
|
||||
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
|
||||
F Makefile.in 30789bf70614bad659351660d76b8e533f3340e9
|
||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||
@ -175,7 +175,7 @@ F src/vdbeapi.c f14174843bf4be2c9afdf2ef48b61e7c3ac62d7c
|
||||
F src/vdbeaux.c db33a4c2477546da05e772352be43896d24d51d5
|
||||
F src/vdbeblob.c e386d49d8354aa5a58f0a7f2794303442c149120
|
||||
F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6
|
||||
F src/vdbemem.c 3da7f7fa7f2ab06a5cbaff132898b07e4d095220
|
||||
F src/vdbemem.c a86119b5ccc41ab8653e4746f83d591ff0ae892e
|
||||
F src/vtab.c 03014b2bfa8096ecac5fcdc80d34cd76e06af52a
|
||||
F src/where.c 9705df3c2b78ea8e02a768be8ac5d3f7a2902f1e
|
||||
F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
|
||||
@ -605,7 +605,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
|
||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
||||
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
|
||||
P 8cbd46517f407b3b1ce187b623db10f00aa415ea
|
||||
R 911083b5c48b851385eee47775792145
|
||||
P 6de0ee49073c7a47d5e10495b569b33df76d1448
|
||||
R 72b005345d91bd390788cc14572cdea6
|
||||
U drh
|
||||
Z ec1836639b43428a4a6ed94e2aced93a
|
||||
Z f60ae65829aa8eb88bba7196814bec78
|
||||
|
@ -1 +1 @@
|
||||
6de0ee49073c7a47d5e10495b569b33df76d1448
|
||||
4744257d3cd2dd96485fde6d9f60542714383421
|
@ -288,6 +288,38 @@ void sqlite3VdbeMemRelease(Mem *p){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Convert a 64-bit IEEE double into a 64-bit signed integer.
|
||||
** If the double is too large, return 0x8000000000000000.
|
||||
**
|
||||
** Most systems appear to do this simply by assigning
|
||||
** variables and without the extra range tests. But
|
||||
** there are reports that windows throws an expection
|
||||
** if the floating point value is out of range. (See ticket #2880.)
|
||||
** Because we do not completely understand the problem, we will
|
||||
** take the conservative approach and always do range tests
|
||||
** before attempting the conversion.
|
||||
*/
|
||||
static i64 doubleToInt64(double r){
|
||||
/*
|
||||
** Many compilers we encounter do not define constants for the
|
||||
** minimum and maximum 64-bit integers, or they define them
|
||||
** inconsistently. And many do not understand the "LL" notation.
|
||||
** So we define our own static constants here using nothing
|
||||
** larger than a 32-bit integer constant.
|
||||
*/
|
||||
static const i64 maxInt = (((i64)0x7fffffff)<<32)|0xffffffff;
|
||||
static const i64 minInt = ((i64)0x80000000)<<32;
|
||||
|
||||
if( r<(double)minInt ){
|
||||
return minInt;
|
||||
}else if( r>(double)maxInt ){
|
||||
return minInt;
|
||||
}else{
|
||||
return (i64)r;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Return some kind of integer value which is the best we can do
|
||||
** at representing the value that *pMem describes as an integer.
|
||||
@ -305,7 +337,7 @@ i64 sqlite3VdbeIntValue(Mem *pMem){
|
||||
if( flags & MEM_Int ){
|
||||
return pMem->u.i;
|
||||
}else if( flags & MEM_Real ){
|
||||
return (i64)pMem->r;
|
||||
return doubleToInt64(pMem->r);
|
||||
}else if( flags & (MEM_Str|MEM_Blob) ){
|
||||
i64 value;
|
||||
pMem->flags |= MEM_Str;
|
||||
@ -356,26 +388,8 @@ void sqlite3VdbeIntegerAffinity(Mem *pMem){
|
||||
assert( pMem->flags & MEM_Real );
|
||||
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
|
||||
|
||||
/* It is reported (in ticket #2880) that the BCC 5.5.1 compiler
|
||||
** will corrupt a floating point number on the right-hand side
|
||||
** of an assignment if the lvalue for the assignment is an integer.
|
||||
**
|
||||
** We will attempt to work around this bug in the Borland compiler
|
||||
** by moving the value into a temporary variable first so that if
|
||||
** the assignment into the integer really does corrupt the right-hand
|
||||
** side value, it will corrupt a temporary variable that we do not
|
||||
** care about.
|
||||
*/
|
||||
#ifdef __BORLANDC__
|
||||
{
|
||||
double r = pMem->r;
|
||||
pMem->u.i = r;
|
||||
}
|
||||
#else
|
||||
pMem->u.i = pMem->r;
|
||||
#endif
|
||||
|
||||
if( ((double)pMem->u.i)==pMem->r ){
|
||||
pMem->u.i = doubleToInt64(pMem->r);
|
||||
if( pMem->r==(double)pMem->u.i ){
|
||||
pMem->flags |= MEM_Int;
|
||||
}
|
||||
}
|
||||
@ -414,7 +428,7 @@ int sqlite3VdbeMemNumerify(Mem *pMem){
|
||||
assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 );
|
||||
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
|
||||
r1 = sqlite3VdbeRealValue(pMem);
|
||||
i = (i64)r1;
|
||||
i = doubleToInt64(r1);
|
||||
r2 = (double)i;
|
||||
if( r1==r2 ){
|
||||
sqlite3VdbeMemIntegerify(pMem);
|
||||
|
Loading…
x
Reference in New Issue
Block a user