From 158b9cb965519d7f8d3e4d5f6c45bce842fc51d4 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 5 Mar 2011 20:59:46 +0000 Subject: [PATCH] Fix all known instances of signed-integer overflow. Within SQL expressions, integer overflow now forces coercion to floating point. The shift operators work with any integer right-hand operand with negative values reversing the direction of the shift. FossilOrigin-Name: abf21394124a0af46f072793718964cee2ce55d0 --- manifest | 32 ++++++------ manifest.uuid | 2 +- src/expr.c | 2 +- src/func.c | 9 +--- src/printf.c | 6 ++- src/sqliteInt.h | 3 ++ src/util.c | 128 +++++++++++++++++++++++++++++++++++++++--------- src/vdbe.c | 62 ++++++++++++++--------- src/vdbemem.c | 2 +- test/expr.test | 119 ++++++++++++++++++++++++++++++++++++++++++-- 10 files changed, 288 insertions(+), 77 deletions(-) diff --git a/manifest b/manifest index e8bdbb82a6..c596f893ae 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 -C Fix\san\sinstance\sof\ssigned\sarithmetic\soverflow\sand\san\sone\sbit-shift\soverflow.\nMark\ssix\sother\ssigned\sarithmetic\soverflow\slocations\sthat\sneed\sfixing. -D 2011-03-05T13:54:15.956 +C Fix\sall\sknown\sinstances\sof\ssigned-integer\soverflow.\s\sWithin\sSQL\sexpressions,\ninteger\soverflow\snow\sforces\scoercion\sto\sfloating\spoint.\s\sThe\sshift\soperators\nwork\swith\sany\sinteger\sright-hand\soperand\swith\snegative\svalues\sreversing\nthe\sdirection\sof\sthe\sshift. +D 2011-03-05T20:59:46.394 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 27701a1653595a1f2187dc61c8117e00a6c1d50f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -133,10 +133,10 @@ F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c 7deec4534f3b5a0c3b4a4cbadf809d321f64f9c4 F src/date.c 1548fdac51377e4e7833251de878b4058c148e1b F src/delete.c 7ed8a8c8b5f748ece92df173d7e0f7810c899ebd -F src/expr.c 0afd6a93d95614e57b29d1c6da5f74be5a4d4fbd +F src/expr.c 66c9383e5e1f5259c43ef3aa7883da66cfc0f492 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 17950a28f28b23e8ad3feaac5fc88c324d2f600a -F src/func.c 9b88e09d238eecdb6242bd387901e6d9f7f64531 +F src/func.c 3a8cb2fb2de3e3aed7f39106daf4878d9d17fcce F src/global.c 02335177cf6946fe5525c6f0755cf181140debf3 F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970 @@ -175,7 +175,7 @@ F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050 F src/pcache1.c d548e31beafa792d1994b663a29a5303569efc4e F src/pragma.c a83f320497aee18eda60fc8d854df5897906c2b1 F src/prepare.c 395b3fab1b93f45b6aa194b23ebc201221c47b99 -F src/printf.c 6eb5c70b531464cca4254e70aaafdf2e7da3a743 +F src/printf.c 585a36b6a963df832cfb69505afa3a34ed5ef8a1 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697 @@ -183,7 +183,7 @@ F src/select.c d24406c45dd2442eb2eeaac413439066b149c944 F src/shell.c 649c51979812f77f97507024a4cea480c6862b8b F src/sqlite.h.in ccb23cc9378874c7c72682b739f311474a80848d F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754 -F src/sqliteInt.h 4290fff17fabc6e07fc4338233df0e39e6350ca1 +F src/sqliteInt.h 118481da7db00c4ae2709ed8af6498be900e6ae0 F src/sqliteLimit.h a17dcd3fb775d63b64a43a55c54cb282f9726f44 F src/status.c 4997380fbb915426fef9e500b4872e79c99267fc F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -231,15 +231,15 @@ F src/tokenize.c 604607d6813e9551cf5189d899e0a25c12681080 F src/trigger.c b8bedb9c0084ceb51a40f54fcca2ce048c8de852 F src/update.c c40aedd40baf460806f1c9f2cbe4a1dac445ee91 F src/utf.c 1baeeac91707a4df97ccc6141ec0f808278af685 -F src/util.c 77572d1f37c5b319d9e735c745349304791f7ba5 +F src/util.c c849a1e77d00a8a28429a22818155dbf9c311fee F src/vacuum.c 924bd1bcee2dfb05376f79845bd3b4cec7b54b2f -F src/vdbe.c 953d44f0fbd72bf73a278c10e7bdd9164235260d +F src/vdbe.c 038e5689e48cd6597158c5dc34f8d40a03a87ad7 F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2 F src/vdbeInt.h 6e6f28e9bccc6c703dca1372fd661c57b5c15fb0 F src/vdbeapi.c 8e9324fd35eb70d0b5904bd1af40f2598744dc4d F src/vdbeaux.c 3ce2588ffe921e457d00baee7dd409afabe8c8af F src/vdbeblob.c 18955f0ee6b133cd08e1592010cb9a6b11e9984c -F src/vdbemem.c 0fa2ed786cd207d5b988afef3562a8e663a75b50 +F src/vdbemem.c d8f713bcc3e176040d3e2bb4fbffc3b31faa4252 F src/vdbetrace.c 3ba13bc32bdf16d2bdea523245fd16736bed67b5 F src/vtab.c b297e8fa656ab5e66244ab15680d68db0adbec30 F src/wal.c 5386fb5e13c2daa8ab9062597fdc17bd849da371 @@ -383,7 +383,7 @@ F test/eval.test bc269c365ba877554948441e91ad5373f9f91be3 F test/exclusive.test 53e1841b422e554cecf0160f937c473d6d0e3062 F test/exclusive2.test 343d55130c12c67b8bf10407acec043a6c26c86b F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7 -F test/expr.test 620a636cf7b7d4e5834a0b9d83a4da372e24a7b7 +F test/expr.test 19e8ac40313e2282a47b586d11c4892040990d3a F test/fallocate.test 43dc34b8c24be6baffadc3b4401ee15710ce83c6 F test/filectrl.test 97003734290887566e01dded09dc9e99cb937e9e F test/filefmt.test f178cfc29501a14565954c961b226e61877dd32c @@ -914,14 +914,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 952f5e8c69904c48f2decfabf8ea60a2e9f3e134 -R c0946fb5d31ae3d41275b61febc12359 +P 04abab71ecd52f6070b9f84781a3df3d6dba7722 +R dffbfc883d2df8713fd0ba30b453b561 U drh -Z 4b81d66afc295ddd153d99c651678bf2 +Z e566f37c8f9e6003556e493773a7db62 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) -iD8DBQFNckCLoxKgR168RlERAq5MAJwIkQItYpj2jIMbedpVkYZIN7SirACePysg -Jf8UO88YpxqtY86joGQ7FqQ= -=f5iN +iD8DBQFNcqRGoxKgR168RlERAlK6AJ9gnf6EDR2ZKhaKkoiA1Nkl5MKeDgCeOJxY +dz92w6QJZQImuyiplDh238s= +=sTB2 -----END PGP SIGNATURE----- diff --git a/manifest.uuid b/manifest.uuid index ad8d2b9252..6a05b41f73 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -04abab71ecd52f6070b9f84781a3df3d6dba7722 \ No newline at end of file +abf21394124a0af46f072793718964cee2ce55d0 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 57243c74e8..b938d9657b 100644 --- a/src/expr.c +++ b/src/expr.c @@ -1964,7 +1964,7 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){ c = sqlite3Atoi64(z, &value, sqlite3Strlen30(z), SQLITE_UTF8); if( c==0 || (c==2 && negFlag) ){ char *zV; - if( negFlag ){ value = -value; } /* CLANG */ + if( negFlag ){ value = c==2 ? SMALLEST_INT64 : -value; } zV = dup8bytes(v, (char*)&value); sqlite3VdbeAddOp4(v, OP_Int64, 0, iMem, 0, zV, P4_INT64); }else{ diff --git a/src/func.c b/src/func.c index 2f21ac0e3d..6a4f7c09c3 100644 --- a/src/func.c +++ b/src/func.c @@ -1239,13 +1239,8 @@ static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){ if( type==SQLITE_INTEGER ){ i64 v = sqlite3_value_int64(argv[0]); p->rSum += v; - if( (p->approx|p->overflow)==0 ){ - i64 iNewSum = p->iSum + v; /* CLANG */ - int s1 = (int)(p->iSum >> (sizeof(i64)*8-1)); - int s2 = (int)(v >> (sizeof(i64)*8-1)); - int s3 = (int)(iNewSum >> (sizeof(i64)*8-1)); - p->overflow = ((s1&s2&~s3) | (~s1&~s2&s3))?1:0; - p->iSum = iNewSum; + if( (p->approx|p->overflow)==0 && sqlite3AddInt64(&p->iSum, v) ){ + p->overflow = 1; } }else{ p->rSum += sqlite3_value_double(argv[0]); diff --git a/src/printf.c b/src/printf.c index 21b6c0e11a..2a3dd81d7d 100644 --- a/src/printf.c +++ b/src/printf.c @@ -400,7 +400,11 @@ void sqlite3VXPrintf( v = va_arg(ap,int); } if( v<0 ){ - longvalue = -v; /* CLANG */ + if( v==SMALLEST_INT64 ){ + longvalue = ((u64)1)<<63; + }else{ + longvalue = -v; + } prefix = '-'; }else{ longvalue = v; diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 2987dcd483..bbf1b16883 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2903,6 +2903,9 @@ Expr *sqlite3ExprSetCollByToken(Parse *pParse, Expr*, Token*); int sqlite3CheckCollSeq(Parse *, CollSeq *); int sqlite3CheckObjectName(Parse *, const char *); void sqlite3VdbeSetChanges(sqlite3 *, int); +int sqlite3AddInt64(i64*,i64); +int sqlite3SubInt64(i64*,i64); +int sqlite3MulInt64(i64*,i64); const void *sqlite3ValueText(sqlite3_value*, u8); int sqlite3ValueBytes(sqlite3_value*, u8); diff --git a/src/util.c b/src/util.c index ca22749fa0..b2787974c1 100644 --- a/src/util.c +++ b/src/util.c @@ -441,14 +441,17 @@ static int compare2pow63(const char *zNum, int incr){ /* -** Convert zNum to a 64-bit signed integer and write -** the value of the integer into *pNum. -** If zNum is exactly 9223372036854665808, return 2. -** This is a special case as the context will determine -** if it is too big (used as a negative). -** If zNum is not an integer or is an integer that -** is too large to be expressed with 64 bits, -** then return 1. Otherwise return 0. +** Convert zNum to a 64-bit signed integer. +** +** If the zNum value is representable as a 64-bit twos-complement +** integer, then write that value into *pNum and return 0. +** +** If zNum is exactly 9223372036854665808, return 2. This special +** case is broken out because while 9223372036854665808 cannot be a +** signed 64-bit integer, its negative -9223372036854665808 can be. +** +** If zNum is too big for a 64-bit integer and is not +** 9223372036854665808 then return 1. ** ** length is the number of bytes in the string (bytes, not characters). ** The string is not necessarily zero-terminated. The encoding is @@ -456,7 +459,7 @@ static int compare2pow63(const char *zNum, int incr){ */ int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){ int incr = (enc==SQLITE_UTF8?1:2); - i64 v = 0; + u64 u = 0; int neg = 0; /* assume positive */ int i; int c = 0; @@ -464,20 +467,26 @@ int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){ const char *zEnd = zNum + length; if( enc==SQLITE_UTF16BE ) zNum++; while( zNum=zEnd ) goto do_atoi_calc; - if( *zNum=='-' ){ - neg = 1; - zNum+=incr; - }else if( *zNum=='+' ){ - zNum+=incr; + if( zNum='0' && c<='9'; i+=incr){ - v = v*10 + c - '0'; /* CLANG */ + u = u*10 + c - '0'; + } + if( u>LARGEST_INT64 ){ + *pNum = SMALLEST_INT64; + }else if( neg ){ + *pNum = -(i64)u; + }else{ + *pNum = (i64)u; } - *pNum = neg ? -v : v; /* CLANG */ testcase( i==18 ); testcase( i==19 ); testcase( i==20 ); @@ -487,14 +496,25 @@ do_atoi_calc: return 1; }else if( i<19*incr ){ /* Less than 19 digits, so we know that it fits in 64 bits */ + assert( u<=LARGEST_INT64 ); return 0; }else{ - /* 19-digit numbers must be no larger than 9223372036854775807 if positive - ** or 9223372036854775808 if negative. Note that 9223372036854665808 - ** is 2^63. Return 1 if to large */ - c=compare2pow63(zNum, incr); - if( c==0 && neg==0 ) return 2; /* too big, exactly 9223372036854665808 */ - return c0 ){ + /* zNum is greater than 9223372036854775808 so it overflows */ + return 1; + }else{ + /* zNum is exactly 9223372036854775808. Fits if negative. The + ** special case 2 overflow if positive */ + assert( u-1==LARGEST_INT64 ); + assert( (*pNum)==SMALLEST_INT64 ); + return neg ? 0 : 2; + } } } @@ -1060,3 +1080,63 @@ int sqlite3SafetyCheckSickOrOk(sqlite3 *db){ return 1; } } + +/* +** Attempt to add, substract, or multiply the 64-bit signed value iB against +** the other 64-bit signed integer at *pA and store the result in *pA. +** Return 0 on success. Or if the operation would have resulted in an +** overflow, leave *pA unchanged and return 1. +*/ +int sqlite3AddInt64(i64 *pA, i64 iB){ + i64 iA = *pA; + testcase( iA==0 ); testcase( iA==1 ); + testcase( iB==-1 ); testcase( iB==0 ); + if( iB>=0 ){ + testcase( iA>0 && LARGEST_INT64 - iA == iB ); + testcase( iA>0 && LARGEST_INT64 - iA == iB - 1 ); + if( iA>0 && LARGEST_INT64 - iA < iB ) return 1; + *pA += iB; + }else{ + testcase( iA<0 && -(iA + LARGEST_INT64) == iB + 1 ); + testcase( iA<0 && -(iA + LARGEST_INT64) == iB + 2 ); + if( iA<0 && -(iA + LARGEST_INT64) > iB + 1 ) return 1; + *pA += iB; + } + return 0; +} +int sqlite3SubInt64(i64 *pA, i64 iB){ + testcase( iB==SMALLEST_INT64+1 ); + if( iB==SMALLEST_INT64 ){ + testcase( (*pA)==(-1) ); testcase( (*pA)==0 ); + if( (*pA)>=0 ) return 1; + *pA -= iB; + return 0; + }else{ + return sqlite3AddInt64(pA, -iB); + } +} +#define TWOPOWER32 (((i64)1)<<32) +#define TWOPOWER31 (((i64)1)<<31) +int sqlite3MulInt64(i64 *pA, i64 iB){ + i64 iA = *pA; + i64 iA1, iA0, iB1, iB0, r; + +// if( iB==1 ){ return 0; } +// if( iA==1 ){ *pA = iB; return 0; } + iA1 = iA/TWOPOWER32; + iA0 = iA % TWOPOWER32; + iB1 = iB/TWOPOWER32; + iB0 = iB % TWOPOWER32; + if( iA1*iB1 != 0 ) return 1; + r = iA1*iB0; + if( sqlite3AddInt64(&r, iA0*iB1) ) return 1; + testcase( r==(-TWOPOWER31)-1 ); + testcase( r==(-TWOPOWER31) ); + testcase( r==TWOPOWER31 ); + testcase( r==TWOPOWER31-1 ); + if( r<(-TWOPOWER31) || r>=TWOPOWER31 ) return 1; + r *= TWOPOWER32; + if( sqlite3AddInt64(&r, iA0*iB0) ) return 1; + *pA = r; + return 0; +} diff --git a/src/vdbe.c b/src/vdbe.c index 3a7397687b..823688e797 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -1246,19 +1246,12 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ iA = pIn1->u.i; iB = pIn2->u.i; switch( pOp->opcode ){ - case OP_Add: iB += iA; break; /* CLANG */ - case OP_Subtract: iB -= iA; break; - case OP_Multiply: iB *= iA; break; + case OP_Add: if( sqlite3AddInt64(&iB,iA) ) goto fp_math; break; + case OP_Subtract: if( sqlite3SubInt64(&iB,iA) ) goto fp_math; break; + case OP_Multiply: if( sqlite3MulInt64(&iB,iA) ) goto fp_math; break; case OP_Divide: { if( iA==0 ) goto arithmetic_result_is_null; - /* Dividing the largest possible negative 64-bit integer (1<<63) by - ** -1 returns an integer too large to store in a 64-bit data-type. On - ** some architectures, the value overflows to (1<<63). On others, - ** a SIGFPE is issued. The following statement normalizes this - ** behavior so that all architectures behave as if integer - ** overflow occurred. - */ - if( iA==-1 && iB==SMALLEST_INT64 ) iA = 1; + if( iA==-1 && iB==SMALLEST_INT64 ) goto fp_math; iB /= iA; break; } @@ -1272,6 +1265,7 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ pOut->u.i = iB; MemSetTypeFlag(pOut, MEM_Int); }else{ +fp_math: rA = sqlite3VdbeRealValue(pIn1); rB = sqlite3VdbeRealValue(pIn2); switch( pOp->opcode ){ @@ -1466,8 +1460,10 @@ case OP_BitAnd: /* same as TK_BITAND, in1, in2, out3 */ case OP_BitOr: /* same as TK_BITOR, in1, in2, out3 */ case OP_ShiftLeft: /* same as TK_LSHIFT, in1, in2, out3 */ case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */ - i64 a; - i64 b; + i64 iA; + u64 uA; + i64 iB; + u8 op; pIn1 = &aMem[pOp->p1]; pIn2 = &aMem[pOp->p2]; @@ -1476,16 +1472,38 @@ case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */ sqlite3VdbeMemSetNull(pOut); break; } - a = sqlite3VdbeIntValue(pIn2); - b = sqlite3VdbeIntValue(pIn1); - switch( pOp->opcode ){ - case OP_BitAnd: a &= b; break; - case OP_BitOr: a |= b; break; - case OP_ShiftLeft: a <<= b; break; - default: assert( pOp->opcode==OP_ShiftRight ); - a >>= b; break; + iA = sqlite3VdbeIntValue(pIn2); + iB = sqlite3VdbeIntValue(pIn1); + op = pOp->opcode; + if( op==OP_BitAnd ){ + iA &= iB; + }else if( op==OP_BitOr ){ + iA |= iB; + }else if( iB!=0 ){ + assert( op==OP_ShiftRight || op==OP_ShiftLeft ); + + /* If shifting by a negative amount, shift in the other direction */ + if( iB<0 ){ + assert( OP_ShiftRight==OP_ShiftLeft+1 ); + op = 2*OP_ShiftLeft + 1 - op; + iB = iB>(-64) ? -iB : 64; + } + + if( iB>=64 ){ + iA = (iA>=0 || op==OP_ShiftLeft) ? 0 : -1; + }else{ + memcpy(&uA, &iA, sizeof(uA)); + if( op==OP_ShiftLeft ){ + uA <<= iB; + }else{ + uA >>= iB; + /* Sign-extend on a right shift of a negative number */ + if( iA<0 ) uA |= ((((u64)0xffffffff)<<32)|0xffffffff) << (64-iB); + } + memcpy(&iA, &uA, sizeof(iA)); + } } - pOut->u.i = a; + pOut->u.i = iA; MemSetTypeFlag(pOut, MEM_Int); break; } diff --git a/src/vdbemem.c b/src/vdbemem.c index 104b93fd66..d2fdeb7ee9 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -367,7 +367,7 @@ i64 sqlite3VdbeIntValue(Mem *pMem){ }else if( flags & MEM_Real ){ return doubleToInt64(pMem->r); }else if( flags & (MEM_Str|MEM_Blob) ){ - i64 value; + i64 value = 0; assert( pMem->z || pMem->n==0 ); testcase( pMem->z==0 ); sqlite3Atoi64(pMem->z, &value, pMem->n, pMem->enc); diff --git a/test/expr.test b/test/expr.test index 140ab8d8b3..5a3d167517 100644 --- a/test/expr.test +++ b/test/expr.test @@ -82,8 +82,18 @@ test_expr expr-1.43 {i1=1, i2=2} {i1&i2} {0} test_expr expr-1.43b {i1=1, i2=2} {4&5} {4} test_expr expr-1.44 {i1=1} {~i1} {-2} test_expr expr-1.44b {i1=NULL} {~i1} {{}} -test_expr expr-1.45 {i1=1, i2=3} {i1<>i2} {4} +test_expr expr-1.45a {i1=1, i2=3} {i1<>i2} {8} +test_expr expr-1.45c {i1=1, i2=0} {i1<>i2} {0} +test_expr expr-1.46a {i1=32, i2=3} {i1>>i2} {4} +test_expr expr-1.46b {i1=32, i2=6} {i1>>i2} {0} +test_expr expr-1.46c {i1=-32, i2=3} {i1>>i2} {-4} +test_expr expr-1.46d {i1=-32, i2=100} {i1>>i2} {-1} +test_expr expr-1.46e {i1=32, i2=-3} {i1>>i2} {256} test_expr expr-1.47 {i1=9999999999, i2=8888888888} {i1i2} 1 @@ -154,10 +164,10 @@ ifcapable floatingpoint { } if {[working_64bit_int]} { - test_expr expr-1.106 {i1=0} {(1<<63)/-1} -9223372036854775808 + test_expr expr-1.106 {i1=0} {-9223372036854775808/-1} 9.22337203685478e+18 } -test_expr expr-1.107 {i1=0} {(1<<63)%-1} 0 +test_expr expr-1.107 {i1=0} {-9223372036854775808%-1} 0 test_expr expr-1.108 {i1=0} {1%0} {{}} test_expr expr-1.109 {i1=0} {1/0} {{}} @@ -190,6 +200,107 @@ test_expr expr-1.125 {i1=6, i2=NULL} \ test_expr expr-1.126 {i1=8, i2=8} \ {CASE WHEN i1 IS NOT i2 THEN 'yes' ELSE 'no' END} no +ifcapable floatingpoint {if {[working_64bit_int]} { + test_expr expr-1.200\ + {i1=9223372036854775806, i2=1} {i1+i2} 9223372036854775807 + test_expr expr-1.201\ + {i1=9223372036854775806, i2=2} {i1+i2} 9.22337203685478e+18 + test_expr expr-1.202\ + {i1=9223372036854775806, i2=100000} {i1+i2} 9.22337203685488e+18 + test_expr expr-1.203\ + {i1=9223372036854775807, i2=0} {i1+i2} 9223372036854775807 + test_expr expr-1.204\ + {i1=9223372036854775807, i2=1} {i1+i2} 9.22337203685478e+18 + test_expr expr-1.205\ + {i2=9223372036854775806, i1=1} {i1+i2} 9223372036854775807 + test_expr expr-1.206\ + {i2=9223372036854775806, i1=2} {i1+i2} 9.22337203685478e+18 + test_expr expr-1.207\ + {i2=9223372036854775806, i1=100000} {i1+i2} 9.22337203685488e+18 + test_expr expr-1.208\ + {i2=9223372036854775807, i1=0} {i1+i2} 9223372036854775807 + test_expr expr-1.209\ + {i2=9223372036854775807, i1=1} {i1+i2} 9.22337203685478e+18 + test_expr expr-1.210\ + {i1=-9223372036854775807, i2=-1} {i1+i2} -9223372036854775808 + test_expr expr-1.211\ + {i1=-9223372036854775807, i2=-2} {i1+i2} -9.22337203685478e+18 + test_expr expr-1.212\ + {i1=-9223372036854775807, i2=-100000} {i1+i2} -9.22337203685488e+18 + test_expr expr-1.213\ + {i1=-9223372036854775808, i2=0} {i1+i2} -9223372036854775808 + test_expr expr-1.214\ + {i1=-9223372036854775808, i2=-1} {i1+i2} -9.22337203685478e+18 + test_expr expr-1.215\ + {i2=-9223372036854775807, i1=-1} {i1+i2} -9223372036854775808 + test_expr expr-1.216\ + {i2=-9223372036854775807, i1=-2} {i1+i2} -9.22337203685478e+18 + test_expr expr-1.217\ + {i2=-9223372036854775807, i1=-100000} {i1+i2} -9.22337203685488e+18 + test_expr expr-1.218\ + {i2=-9223372036854775808, i1=0} {i1+i2} -9223372036854775808 + test_expr expr-1.219\ + {i2=-9223372036854775808, i1=-1} {i1+i2} -9.22337203685478e+18 + test_expr expr-1.220\ + {i1=9223372036854775806, i2=-1} {i1-i2} 9223372036854775807 + test_expr expr-1.221\ + {i1=9223372036854775806, i2=-2} {i1-i2} 9.22337203685478e+18 + test_expr expr-1.222\ + {i1=9223372036854775806, i2=-100000} {i1-i2} 9.22337203685488e+18 + test_expr expr-1.223\ + {i1=9223372036854775807, i2=0} {i1-i2} 9223372036854775807 + test_expr expr-1.224\ + {i1=9223372036854775807, i2=-1} {i1-i2} 9.22337203685478e+18 + test_expr expr-1.225\ + {i2=-9223372036854775806, i1=1} {i1-i2} 9223372036854775807 + test_expr expr-1.226\ + {i2=-9223372036854775806, i1=2} {i1-i2} 9.22337203685478e+18 + test_expr expr-1.227\ + {i2=-9223372036854775806, i1=100000} {i1-i2} 9.22337203685488e+18 + test_expr expr-1.228\ + {i2=-9223372036854775807, i1=0} {i1-i2} 9223372036854775807 + test_expr expr-1.229\ + {i2=-9223372036854775807, i1=1} {i1-i2} 9.22337203685478e+18 + test_expr expr-1.230\ + {i1=-9223372036854775807, i2=1} {i1-i2} -9223372036854775808 + test_expr expr-1.231\ + {i1=-9223372036854775807, i2=2} {i1-i2} -9.22337203685478e+18 + test_expr expr-1.232\ + {i1=-9223372036854775807, i2=100000} {i1-i2} -9.22337203685488e+18 + test_expr expr-1.233\ + {i1=-9223372036854775808, i2=0} {i1-i2} -9223372036854775808 + test_expr expr-1.234\ + {i1=-9223372036854775808, i2=1} {i1-i2} -9.22337203685478e+18 + test_expr expr-1.235\ + {i2=9223372036854775807, i1=-1} {i1-i2} -9223372036854775808 + test_expr expr-1.236\ + {i2=9223372036854775807, i1=-2} {i1-i2} -9.22337203685478e+18 + test_expr expr-1.237\ + {i2=9223372036854775807, i1=-100000} {i1-i2} -9.22337203685488e+18 + test_expr expr-1.238\ + {i2=9223372036854775807, i1=0} {i1-i2} -9223372036854775807 + test_expr expr-1.239\ + {i2=9223372036854775807, i1=-1} {i1-i2} -9223372036854775808 + + test_expr expr-1.250\ + {i1=4294967296, i2=2147483648} {i1*i2} 9.22337203685478e+18 + test_expr expr-1.251\ + {i1=4294967296, i2=2147483647} {i1*i2} 9223372032559808512 + test_expr expr-1.252\ + {i1=-4294967296, i2=2147483648} {i1*i2} -9223372036854775808 + test_expr expr-1.253\ + {i1=-4294967296, i2=2147483647} {i1*i2} -9223372032559808512 + test_expr expr-1.254\ + {i1=4294967296, i2=-2147483648} {i1*i2} -9223372036854775808 + test_expr expr-1.255\ + {i1=4294967296, i2=-2147483647} {i1*i2} -9223372032559808512 + test_expr expr-1.256\ + {i1=-4294967296, i2=-2147483648} {i1*i2} 9.22337203685478e+18 + test_expr expr-1.257\ + {i1=-4294967296, i2=-2147483647} {i1*i2} 9223372032559808512 + +}} + ifcapable floatingpoint { test_expr expr-2.1 {r1=1.23, r2=2.34} {r1+r2} 3.57 test_expr expr-2.2 {r1=1.23, r2=2.34} {r1-r2} -1.11