mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-09 14:21:03 +03:00
Correctly handle 64-bit integers in SQL statements. (CVS 1408)
FossilOrigin-Name: 34f03ba6a9d6e2144d0c6cbbbeb37b4c69705f1f
This commit is contained in:
79
src/util.c
79
src/util.c
@@ -14,7 +14,7 @@
|
||||
** This file contains functions for allocating memory, comparing
|
||||
** strings, and stuff like that.
|
||||
**
|
||||
** $Id: util.c,v 1.85 2004/05/19 10:34:57 danielk1977 Exp $
|
||||
** $Id: util.c,v 1.86 2004/05/19 20:41:03 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <stdarg.h>
|
||||
@@ -610,6 +610,38 @@ double sqlite3AtoF(const char *z, const char **pzEnd){
|
||||
return sign<0 ? -v1 : v1;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return TRUE if zNum is a 64-bit signed integer and write
|
||||
** the value of the integer into *pNum. If zNum is not an integer
|
||||
** or is an integer that is too large to be expressed with 64 bits,
|
||||
** then return false. If n>0 and the integer is string is not
|
||||
** exactly n bytes long, return false.
|
||||
**
|
||||
** When this routine was originally written it dealt with only
|
||||
** 32-bit numbers. At that time, it was much faster than the
|
||||
** atoi() library routine in RedHat 7.2.
|
||||
*/
|
||||
int sqlite3atoi64(const char *zNum, i64 *pNum){
|
||||
i64 v = 0;
|
||||
int neg;
|
||||
int i, c;
|
||||
if( *zNum=='-' ){
|
||||
neg = 1;
|
||||
zNum++;
|
||||
}else if( *zNum=='+' ){
|
||||
neg = 0;
|
||||
zNum++;
|
||||
}else{
|
||||
neg = 0;
|
||||
}
|
||||
for(i=0; (c=zNum[i])>='0' && c<='9'; i++){
|
||||
v = v*10 + c - '0';
|
||||
}
|
||||
*pNum = neg ? -v : v;
|
||||
return c==0 && i>0 &&
|
||||
(i<19 || (i==19 && memcmp(zNum,"9223372036854775807",19)<=0));
|
||||
}
|
||||
|
||||
/*
|
||||
** The string zNum represents an integer. There might be some other
|
||||
** information following the integer too, but that part is ignored.
|
||||
@@ -621,13 +653,55 @@ double sqlite3AtoF(const char *z, const char **pzEnd){
|
||||
** 2147483648 will not fit in 32 bits. So it seems safer to return
|
||||
** false.
|
||||
*/
|
||||
int sqlite3FitsIn32Bits(const char *zNum){
|
||||
static int sqlite3FitsIn32Bits(const char *zNum){
|
||||
int i, c;
|
||||
if( *zNum=='-' || *zNum=='+' ) zNum++;
|
||||
for(i=0; (c=zNum[i])>='0' && c<='9'; i++){}
|
||||
return i<10 || (i==10 && memcmp(zNum,"2147483647",10)<=0);
|
||||
}
|
||||
|
||||
/*
|
||||
** If zNum represents an integer that will fit in 32-bits, then set
|
||||
** *pValue to that integer and return true. Otherwise return false.
|
||||
*/
|
||||
int sqlite3GetInt32(const char *zNum, int *pValue){
|
||||
if( sqlite3FitsIn32Bits(zNum) ){
|
||||
*pValue = atoi(zNum);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** The string zNum represents an integer. There might be some other
|
||||
** information following the integer too, but that part is ignored.
|
||||
** If the integer that the prefix of zNum represents will fit in a
|
||||
** 64-bit signed integer, return TRUE. Otherwise return FALSE.
|
||||
**
|
||||
** This routine returns FALSE for the string -9223372036854775808 even that
|
||||
** that number will, in theory fit in a 64-bit integer. Positive
|
||||
** 9223373036854775808 will not fit in 64 bits. So it seems safer to return
|
||||
** false.
|
||||
*/
|
||||
int sqlite3FitsIn64Bits(const char *zNum){
|
||||
int i, c;
|
||||
if( *zNum=='-' || *zNum=='+' ) zNum++;
|
||||
for(i=0; (c=zNum[i])>='0' && c<='9'; i++){}
|
||||
return i<19 || (i==19 && memcmp(zNum,"9223372036854775807",19)<=0);
|
||||
}
|
||||
|
||||
/*
|
||||
** If zNum represents an integer that will fit in 64-bits, then set
|
||||
** *pValue to that integer and return true. Otherwise return false.
|
||||
*/
|
||||
int sqlite3GetInt64(const char *zNum, i64 *pValue){
|
||||
if( sqlite3FitsIn64Bits(zNum) ){
|
||||
sqlite3atoi64(zNum, pValue);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This comparison routine is what we use for comparison operations
|
||||
** between numeric values in an SQL expression. "Numeric" is a little
|
||||
** bit misleading here. What we mean is that the strings have a
|
||||
@@ -1180,4 +1254,3 @@ int sqlite3VarintLen(u64 v){
|
||||
}while( v!=0 && i<9 );
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user