mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-11 01:42:22 +03:00
Improved resolution of large integer values in "CAST(x AS NUMERIC)".
FossilOrigin-Name: 7f2bd4ff45fba29528c18cac6da983bd9b164303525d3965056f5b40f85dc83f
This commit is contained in:
38
src/util.c
38
src/util.c
@@ -557,16 +557,12 @@ static int compare2pow63(const char *zNum, int incr){
|
||||
** Convert zNum to a 64-bit signed integer. zNum must be decimal. This
|
||||
** routine does *not* accept hexadecimal notation.
|
||||
**
|
||||
** If the zNum value is representable as a 64-bit twos-complement
|
||||
** integer, then write that value into *pNum and return 0.
|
||||
** Returns:
|
||||
**
|
||||
** If zNum is exactly 9223372036854775808, return 2. This special
|
||||
** case is broken out because while 9223372036854775808 cannot be a
|
||||
** signed 64-bit integer, its negative -9223372036854775808 can be.
|
||||
**
|
||||
** If zNum is too big for a 64-bit integer and is not
|
||||
** 9223372036854775808 or if zNum contains any non-numeric text,
|
||||
** then return 1.
|
||||
** 0 Successful transformation. Fits in a 64-bit signed integer.
|
||||
** 1 Excess text after the integer value
|
||||
** 2 Integer too large for a 64-bit signed integer or is malformed
|
||||
** 3 Special case of 9223372036854775808
|
||||
**
|
||||
** length is the number of bytes in the string (bytes, not characters).
|
||||
** The string is not necessarily zero-terminated. The encoding is
|
||||
@@ -579,6 +575,7 @@ int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
|
||||
int i;
|
||||
int c = 0;
|
||||
int nonNum = 0; /* True if input contains UTF16 with high byte non-zero */
|
||||
int rc; /* Baseline return code */
|
||||
const char *zStart;
|
||||
const char *zEnd = zNum + length;
|
||||
assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
|
||||
@@ -618,31 +615,35 @@ int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
|
||||
testcase( i==20 );
|
||||
if( &zNum[i]<zEnd /* Extra bytes at the end */
|
||||
|| (i==0 && zStart==zNum) /* No digits */
|
||||
|| i>19*incr /* Too many digits */
|
||||
|| nonNum /* UTF16 with high-order bytes non-zero */
|
||||
){
|
||||
rc = 1;
|
||||
}else{
|
||||
rc = 0;
|
||||
}
|
||||
if( i>19*incr ){ /* Too many digits */
|
||||
/* zNum is empty or contains non-numeric text or is longer
|
||||
** than 19 digits (thus guaranteeing that it is too large) */
|
||||
return 1;
|
||||
return 2;
|
||||
}else if( i<19*incr ){
|
||||
/* Less than 19 digits, so we know that it fits in 64 bits */
|
||||
assert( u<=LARGEST_INT64 );
|
||||
return 0;
|
||||
return rc;
|
||||
}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;
|
||||
return rc;
|
||||
}else if( c>0 ){
|
||||
/* zNum is greater than 9223372036854775808 so it overflows */
|
||||
return 1;
|
||||
return 2;
|
||||
}else{
|
||||
/* zNum is exactly 9223372036854775808. Fits if negative. The
|
||||
** special case 2 overflow if positive */
|
||||
assert( u-1==LARGEST_INT64 );
|
||||
return neg ? 0 : 2;
|
||||
return neg ? rc : 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -655,8 +656,9 @@ int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
|
||||
** Returns:
|
||||
**
|
||||
** 0 Successful transformation. Fits in a 64-bit signed integer.
|
||||
** 1 Integer too large for a 64-bit signed integer or is malformed
|
||||
** 2 Special case of 9223372036854775808
|
||||
** 1 Excess text after the integer value
|
||||
** 2 Integer too large for a 64-bit signed integer or is malformed
|
||||
** 3 Special case of 9223372036854775808
|
||||
*/
|
||||
int sqlite3DecOrHexToI64(const char *z, i64 *pOut){
|
||||
#ifndef SQLITE_OMIT_HEX_INTEGER
|
||||
@@ -670,7 +672,7 @@ int sqlite3DecOrHexToI64(const char *z, i64 *pOut){
|
||||
u = u*16 + sqlite3HexToInt(z[k]);
|
||||
}
|
||||
memcpy(pOut, &u, 8);
|
||||
return (z[k]==0 && k-i<=16) ? 0 : 1;
|
||||
return (z[k]==0 && k-i<=16) ? 0 : 2;
|
||||
}else
|
||||
#endif /* SQLITE_OMIT_HEX_INTEGER */
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user