Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | 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. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
abf21394124a0af46f072793718964ce |
User & Date: | drh 2011-03-05 20:59:46.394 |
Context
2011-03-05
| ||
21:41 | Simplifications to the overflow-free multiplier. Also remove some commented-out code that was left in that subroutine by mistake on the previous check-in. (check-in: 55fc25fdab user: drh tags: trunk) | |
20:59 | 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. (check-in: abf2139412 user: drh tags: trunk) | |
13:54 | Fix an instance of signed arithmetic overflow and an one bit-shift overflow. Mark six other signed arithmetic overflow locations that need fixing. (check-in: 04abab71ec user: drh tags: trunk) | |
Changes
Changes to src/expr.c.
︙ | ︙ | |||
1960 1961 1962 1963 1964 1965 1966 | int c; i64 value; const char *z = pExpr->u.zToken; assert( z!=0 ); c = sqlite3Atoi64(z, &value, sqlite3Strlen30(z), SQLITE_UTF8); if( c==0 || (c==2 && negFlag) ){ char *zV; | | | 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 | int c; i64 value; const char *z = pExpr->u.zToken; assert( z!=0 ); c = sqlite3Atoi64(z, &value, sqlite3Strlen30(z), SQLITE_UTF8); if( c==0 || (c==2 && negFlag) ){ char *zV; if( negFlag ){ value = c==2 ? SMALLEST_INT64 : -value; } zV = dup8bytes(v, (char*)&value); sqlite3VdbeAddOp4(v, OP_Int64, 0, iMem, 0, zV, P4_INT64); }else{ #ifdef SQLITE_OMIT_FLOATING_POINT sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z); #else codeReal(v, z, negFlag, iMem); |
︙ | ︙ |
Changes to src/func.c.
︙ | ︙ | |||
1235 1236 1237 1238 1239 1240 1241 | p = sqlite3_aggregate_context(context, sizeof(*p)); type = sqlite3_value_numeric_type(argv[0]); if( p && type!=SQLITE_NULL ){ p->cnt++; if( type==SQLITE_INTEGER ){ i64 v = sqlite3_value_int64(argv[0]); p->rSum += v; | | < < < < | < | 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 | p = sqlite3_aggregate_context(context, sizeof(*p)); type = sqlite3_value_numeric_type(argv[0]); if( p && type!=SQLITE_NULL ){ p->cnt++; if( type==SQLITE_INTEGER ){ i64 v = sqlite3_value_int64(argv[0]); p->rSum += v; if( (p->approx|p->overflow)==0 && sqlite3AddInt64(&p->iSum, v) ){ p->overflow = 1; } }else{ p->rSum += sqlite3_value_double(argv[0]); p->approx = 1; } } } |
︙ | ︙ |
Changes to src/printf.c.
︙ | ︙ | |||
396 397 398 399 400 401 402 | v = va_arg(ap,i64); }else if( flag_long ){ v = va_arg(ap,long int); }else{ v = va_arg(ap,int); } if( v<0 ){ | > > > | > | 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 | v = va_arg(ap,i64); }else if( flag_long ){ v = va_arg(ap,long int); }else{ v = va_arg(ap,int); } if( v<0 ){ if( v==SMALLEST_INT64 ){ longvalue = ((u64)1)<<63; }else{ longvalue = -v; } prefix = '-'; }else{ longvalue = v; if( flag_plussign ) prefix = '+'; else if( flag_blanksign ) prefix = ' '; else prefix = 0; } |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 | CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName); CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr); Expr *sqlite3ExprSetColl(Expr*, CollSeq*); Expr *sqlite3ExprSetCollByToken(Parse *pParse, Expr*, Token*); int sqlite3CheckCollSeq(Parse *, CollSeq *); int sqlite3CheckObjectName(Parse *, const char *); void sqlite3VdbeSetChanges(sqlite3 *, int); const void *sqlite3ValueText(sqlite3_value*, u8); int sqlite3ValueBytes(sqlite3_value*, u8); void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8, void(*)(void*)); void sqlite3ValueFree(sqlite3_value*); sqlite3_value *sqlite3ValueNew(sqlite3 *); | > > > | 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 | CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName); CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr); Expr *sqlite3ExprSetColl(Expr*, CollSeq*); 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); void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8, void(*)(void*)); void sqlite3ValueFree(sqlite3_value*); sqlite3_value *sqlite3ValueNew(sqlite3 *); |
︙ | ︙ |
Changes to src/util.c.
︙ | ︙ | |||
437 438 439 440 441 442 443 | testcase( c==(+1) ); } return c; } /* | | > > | > | | > | | < | | | | | | | | | < > | > > > > > | > > < | < | > | > | > > > > > > > > > > | 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 | testcase( c==(+1) ); } return c; } /* ** 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 ** given by enc. */ int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){ int incr = (enc==SQLITE_UTF8?1:2); u64 u = 0; int neg = 0; /* assume positive */ int i; int c = 0; const char *zStart; const char *zEnd = zNum + length; if( enc==SQLITE_UTF16BE ) zNum++; while( zNum<zEnd && sqlite3Isspace(*zNum) ) zNum+=incr; if( zNum<zEnd ){ if( *zNum=='-' ){ neg = 1; zNum+=incr; }else if( *zNum=='+' ){ zNum+=incr; } } zStart = zNum; while( zNum<zEnd && zNum[0]=='0' ){ zNum+=incr; } /* Skip leading zeros. */ for(i=0; &zNum[i]<zEnd && (c=zNum[i])>='0' && c<='9'; i+=incr){ u = u*10 + c - '0'; } if( u>LARGEST_INT64 ){ *pNum = SMALLEST_INT64; }else if( neg ){ *pNum = -(i64)u; }else{ *pNum = (i64)u; } testcase( i==18 ); testcase( i==19 ); testcase( i==20 ); if( (c!=0 && &zNum[i]<zEnd) || (i==0 && zStart==zNum) || i>19*incr ){ /* zNum is empty or contains non-numeric text or is longer ** than 19 digits (thus guaranteeing that it is too large) */ 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{ /* zNum is a 19-digit numbers. Compare it against 9223372036854775808. */ c = compare2pow63(zNum, incr); if( c<0 ){ /* zNum is less than 9223372036854775808 so it fits */ assert( u<=LARGEST_INT64 ); return 0; }else if( c>0 ){ /* 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; } } } /* ** If zNum represents an integer that will fit in 32-bits, then set ** *pValue to that integer and return true. Otherwise return false. ** |
︙ | ︙ | |||
1056 1057 1058 1059 1060 1061 1062 | testcase( sqlite3GlobalConfig.xLog!=0 ); logBadConnection("invalid"); return 0; }else{ return 1; } } | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 | testcase( sqlite3GlobalConfig.xLog!=0 ); logBadConnection("invalid"); return 0; }else{ 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; } |
Changes to src/vdbe.c.
︙ | ︙ | |||
1242 1243 1244 1245 1246 1247 1248 | pOut = &aMem[pOp->p3]; flags = pIn1->flags | pIn2->flags; if( (flags & MEM_Null)!=0 ) goto arithmetic_result_is_null; if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){ iA = pIn1->u.i; iB = pIn2->u.i; switch( pOp->opcode ){ | | | | < < < < < < < | > | 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 | pOut = &aMem[pOp->p3]; flags = pIn1->flags | pIn2->flags; if( (flags & MEM_Null)!=0 ) goto arithmetic_result_is_null; if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){ iA = pIn1->u.i; iB = pIn2->u.i; switch( pOp->opcode ){ 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; if( iA==-1 && iB==SMALLEST_INT64 ) goto fp_math; iB /= iA; break; } default: { if( iA==0 ) goto arithmetic_result_is_null; if( iA==-1 ) iA = 1; iB %= iA; break; } } pOut->u.i = iB; MemSetTypeFlag(pOut, MEM_Int); }else{ fp_math: rA = sqlite3VdbeRealValue(pIn1); rB = sqlite3VdbeRealValue(pIn2); switch( pOp->opcode ){ case OP_Add: rB += rA; break; case OP_Subtract: rB -= rA; break; case OP_Multiply: rB *= rA; break; case OP_Divide: { |
︙ | ︙ | |||
1462 1463 1464 1465 1466 1467 1468 | ** Store the result in register P3. ** If either input is NULL, the result is NULL. */ 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 */ | | > | > | | | | > > > > > | > > > | > > | > > > > > > > | > > | > > > | | 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 | ** Store the result in register P3. ** If either input is NULL, the result is NULL. */ 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 iA; u64 uA; i64 iB; u8 op; pIn1 = &aMem[pOp->p1]; pIn2 = &aMem[pOp->p2]; pOut = &aMem[pOp->p3]; if( (pIn1->flags | pIn2->flags) & MEM_Null ){ sqlite3VdbeMemSetNull(pOut); 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 = iA; MemSetTypeFlag(pOut, MEM_Int); break; } /* Opcode: AddImm P1 P2 * * * ** ** Add the constant P2 to the value in register P1. |
︙ | ︙ |
Changes to src/vdbemem.c.
︙ | ︙ | |||
363 364 365 366 367 368 369 | assert( EIGHT_BYTE_ALIGNMENT(pMem) ); flags = pMem->flags; if( flags & MEM_Int ){ return pMem->u.i; }else if( flags & MEM_Real ){ return doubleToInt64(pMem->r); }else if( flags & (MEM_Str|MEM_Blob) ){ | | | 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 | assert( EIGHT_BYTE_ALIGNMENT(pMem) ); flags = pMem->flags; if( flags & MEM_Int ){ return pMem->u.i; }else if( flags & MEM_Real ){ return doubleToInt64(pMem->r); }else if( flags & (MEM_Str|MEM_Blob) ){ i64 value = 0; assert( pMem->z || pMem->n==0 ); testcase( pMem->z==0 ); sqlite3Atoi64(pMem->z, &value, pMem->n, pMem->enc); return value; }else{ return 0; } |
︙ | ︙ |
Changes to test/expr.test.
︙ | ︙ | |||
78 79 80 81 82 83 84 | test_expr expr-1.41 {i1=1, i2=2} {-(i2+i1)} {-3} test_expr expr-1.42 {i1=1, i2=2} {i1|i2} {3} test_expr expr-1.42b {i1=1, i2=2} {4|2} {6} 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} {{}} | | > > > > > > | > > > > | 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | test_expr expr-1.41 {i1=1, i2=2} {-(i2+i1)} {-3} test_expr expr-1.42 {i1=1, i2=2} {i1|i2} {3} test_expr expr-1.42b {i1=1, i2=2} {4|2} {6} 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.45a {i1=1, i2=3} {i1<<i2} {8} test_expr expr-1.45b {i1=1, i2=-3} {i1>>i2} {8} test_expr expr-1.45c {i1=1, i2=0} {i1<<i2} {1} test_expr expr-1.45d {i1=1, i2=62} {i1<<i2} {4611686018427387904} test_expr expr-1.45e {i1=1, i2=63} {i1<<i2} {-9223372036854775808} test_expr expr-1.45f {i1=1, i2=64} {i1<<i2} {0} test_expr expr-1.45g {i1=32, i2=-9223372036854775808} {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} {i1<i2} 0 test_expr expr-1.48 {i1=9999999999, i2=8888888888} {i1=i2} 0 test_expr expr-1.49 {i1=9999999999, i2=8888888888} {i1>i2} 1 test_expr expr-1.50 {i1=99999999999, i2=99999999998} {i1<i2} 0 test_expr expr-1.51 {i1=99999999999, i2=99999999998} {i1=i2} 0 test_expr expr-1.52 {i1=99999999999, i2=99999999998} {i1>i2} 1 test_expr expr-1.53 {i1=099999999999, i2=99999999999} {i1<i2} 0 |
︙ | ︙ | |||
150 151 152 153 154 155 156 | ifcapable floatingpoint { test_expr expr-1.103 {i1=0} {(-2147483648.0 % -1)} 0.0 test_expr expr-1.104 {i1=0} {(-9223372036854775808.0 % -1)} 0.0 test_expr expr-1.105 {i1=0} {(-9223372036854775808.0 / -1)>1} 1 } if {[working_64bit_int]} { | | | | 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | ifcapable floatingpoint { test_expr expr-1.103 {i1=0} {(-2147483648.0 % -1)} 0.0 test_expr expr-1.104 {i1=0} {(-9223372036854775808.0 % -1)} 0.0 test_expr expr-1.105 {i1=0} {(-9223372036854775808.0 / -1)>1} 1 } if {[working_64bit_int]} { test_expr expr-1.106 {i1=0} {-9223372036854775808/-1} 9.22337203685478e+18 } 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} {{}} if {[working_64bit_int]} { test_expr expr-1.110 {i1=0} {-9223372036854775807/-1} 9223372036854775807 } |
︙ | ︙ | |||
185 186 187 188 189 190 191 192 193 194 195 196 197 198 | {CASE WHEN i1 IS NOT i2 THEN 'yes' ELSE 'no' END} yes test_expr expr-1.124 {i1=NULL, i2=NULL} \ {CASE WHEN i1 IS NOT i2 THEN 'yes' ELSE 'no' END} no test_expr expr-1.125 {i1=6, i2=NULL} \ {CASE WHEN i1 IS NOT i2 THEN 'yes' ELSE 'no' END} yes test_expr expr-1.126 {i1=8, i2=8} \ {CASE WHEN i1 IS NOT i2 THEN 'yes' ELSE 'no' END} no 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 test_expr expr-2.3 {r1=1.23, r2=2.34} {r1*r2} 2.8782 } set tcl_precision 15 | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 | {CASE WHEN i1 IS NOT i2 THEN 'yes' ELSE 'no' END} yes test_expr expr-1.124 {i1=NULL, i2=NULL} \ {CASE WHEN i1 IS NOT i2 THEN 'yes' ELSE 'no' END} no test_expr expr-1.125 {i1=6, i2=NULL} \ {CASE WHEN i1 IS NOT i2 THEN 'yes' ELSE 'no' END} yes 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 test_expr expr-2.3 {r1=1.23, r2=2.34} {r1*r2} 2.8782 } set tcl_precision 15 |
︙ | ︙ |