Change the hex literal processing so that only the SQL parser understands

hex literals.  Casting and coercing string literals into numeric values does
not understand hexadecimal integers.  This preserves backwards compatibility.
Also:  Throw an error on any hex literal that is too big to fit into 64 bits.

FossilOrigin-Name: 6c6f0de59bf96b79c8ace8c9bfe48c7a6a306a50
This commit is contained in:
drh 2014-07-23 13:40:49 +00:00
parent 5ec659cfcb
commit 9296c18a50
8 changed files with 93 additions and 101 deletions

View File

@ -1,5 +1,5 @@
C Casting\shex\sliterals\sdirectly\sfrom\sstring\sto\sfloat\salways\sresults\sin\sa\npositive\snumber.
D 2014-07-23T02:07:11.054
C Change\sthe\shex\sliteral\sprocessing\sso\sthat\sonly\sthe\sSQL\sparser\sunderstands\nhex\sliterals.\s\sCasting\sand\scoercing\sstring\sliterals\sinto\snumeric\svalues\sdoes\nnot\sunderstand\shexadecimal\sintegers.\s\sThis\spreserves\sbackwards\scompatibility.\nAlso:\s\sThrow\san\serror\son\sany\shex\sliteral\sthat\sis\stoo\sbig\sto\sfit\sinto\s64\sbits.
D 2014-07-23T13:40:49.410
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@ -176,7 +176,7 @@ F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
F src/ctime.c 0231df905e2c4abba4483ee18ffc05adc321df2a
F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
F src/delete.c bcf8f72126cea80fc3d5bc5494cf19b3f8935aaf
F src/expr.c 40d06d1543b1355aa02efa9666178f7642a96ed6
F src/expr.c b1ffac76b69ae005ca38eba6dcdefa5d65eb5c95
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c a549cff9fe8b736cdae21650ea0af6de29b77619
F src/func.c 3bc223ea36cd29a91c481485343d0ee4257ab8dc
@ -189,7 +189,7 @@ F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
F src/loadext.c 867c7b330b740c6c917af9956b13b81d0a048303
F src/main.c 1a420efa9a34e8603c4807886408cba5546b87f9
F src/main.c cfdb2aa5d248ff1af60227cc3f6d485ba86f92dc
F src/malloc.c 0203ebce9152c6a0e5de520140b8ba65187350be
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c0c990fcaddff810ea277b4fb5d9138603dd5d4b
@ -216,7 +216,7 @@ F src/parse.y 22d6a074e5f5a7258947a1dc55a9bf946b765dd0
F src/pcache.c d8eafac28290d4bb80332005435db44991d07fc2
F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
F src/pcache1.c 102e6f5a2fbc646154463eb856d1fd716867b64c
F src/pragma.c 810ef31ccfaa233201dcf100637a9777cc24e897
F src/pragma.c e17c5ea1cb9eb9d93c41bbb7c3a17e747d5e0335
F src/prepare.c 677521ab7132615a8a26107a1d1c3132f44ae337
F src/printf.c af06f66927919730f03479fed6ae9854f73419f4
F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
@ -227,7 +227,7 @@ F src/shell.c 566aee8213372a2e81ba0eb34e9759f7b2574009
F src/sqlite.h.in fd8e3a36b0aded082dc93a4b89c1e85324b4cf75
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
F src/sqliteInt.h b72a09326d7cbd8375ec3d9a04ea5e0cf476beb3
F src/sqliteInt.h 783e77ab498ac05a3fab396dfc1c2d6c2083dced
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
@ -281,7 +281,7 @@ F src/tokenize.c ae45399d6252b4d736af43bee1576ce7bff86aec
F src/trigger.c 66f3470b03b52b395e839155786966e3e037fddb
F src/update.c 01564b3c430f6c7b0a35afaf7aba7987206fa3a5
F src/utf.c a0314e637768a030e6e84a957d0c4f6ba910cc05
F src/util.c eff2c1e5a49a3c64af0fe9f2fb32cada3436a167
F src/util.c 3076bdd51cdbf60a6e2e57fada745be37133c73e
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
F src/vdbe.c fa74c6563486022920db4d73897bd9b837c7441d
F src/vdbe.h c63fad052c9e7388d551e556e119c0bcf6bebdf8
@ -601,7 +601,7 @@ F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26
F test/fuzzer1.test d4c52aaf3ef923da293a2653cfab33d02f718a36
F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
F test/hexlit.test 58b653845b60da52161b5f451db9a89c569187d1
F test/hexlit.test 1dc49cfd1c8938a8f028e392775bc3e61623ec46
F test/hook.test 162d7cef7a2d2b04839fe14402934e6a1b79442f
F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4
F test/in.test 047c4671328e9032ab95666a67021adbbd36e98e
@ -1184,7 +1184,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P 7e1bbacb11a4689b69856450125cae3d045307af
R 8a73a1b568b990d7d0a1847902994baf
P 4b86ccdf4f4eb4339a5706e10ad24f01b6c3939e
R a36ec645688e0ae2f526ebda77270f17
U drh
Z d9d4d7765f779882d47568941cd5db2a
Z 32ccd1ec50cb642ea84793b61793e5b3

View File

@ -1 +1 @@
4b86ccdf4f4eb4339a5706e10ad24f01b6c3939e
6c6f0de59bf96b79c8ace8c9bfe48c7a6a306a50

View File

@ -2075,7 +2075,7 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
i64 value;
const char *z = pExpr->u.zToken;
assert( z!=0 );
c = sqlite3Atoi64(z, &value, sqlite3Strlen30(z), SQLITE_UTF8);
c = sqlite3DecOrHexToI64(z, &value);
if( c==0 || (c==2 && negFlag) ){
char *zV;
if( negFlag ){ value = c==2 ? SMALLEST_INT64 : -value; }
@ -2085,7 +2085,11 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
#ifdef SQLITE_OMIT_FLOATING_POINT
sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z);
#else
if( sqlite3_strnicmp(z,"0x",2)==0 ){
sqlite3ErrorMsg(pParse, "hex literal too big: %s", z);
}else{
codeReal(v, z, negFlag, iMem);
}
#endif
}
}

View File

@ -3409,7 +3409,7 @@ sqlite3_int64 sqlite3_uri_int64(
){
const char *z = sqlite3_uri_parameter(zFilename, zParam);
sqlite3_int64 v;
if( z && sqlite3Atoi64(z, &v, sqlite3Strlen30(z), SQLITE_UTF8)==SQLITE_OK ){
if( z && sqlite3DecOrHexToI64(z, &v)==SQLITE_OK ){
bDflt = v;
}
return bDflt;

View File

@ -1048,7 +1048,7 @@ void sqlite3Pragma(
Pager *pPager = sqlite3BtreePager(pDb->pBt);
i64 iLimit = -2;
if( zRight ){
sqlite3Atoi64(zRight, &iLimit, sqlite3Strlen30(zRight), SQLITE_UTF8);
sqlite3DecOrHexToI64(zRight, &iLimit);
if( iLimit<-1 ) iLimit = -1;
}
iLimit = sqlite3PagerJournalSizeLimit(pPager, iLimit);
@ -1176,7 +1176,7 @@ void sqlite3Pragma(
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
if( zRight ){
int ii;
sqlite3Atoi64(zRight, &sz, sqlite3Strlen30(zRight), SQLITE_UTF8);
sqlite3DecOrHexToI64(zRight, &sz);
if( sz<0 ) sz = sqlite3GlobalConfig.szMmap;
if( pId2->n==0 ) db->szMmap = sz;
for(ii=db->nDb-1; ii>=0; ii--){
@ -2219,7 +2219,7 @@ void sqlite3Pragma(
*/
case PragTyp_SOFT_HEAP_LIMIT: {
sqlite3_int64 N;
if( zRight && sqlite3Atoi64(zRight, &N, 1000000, SQLITE_UTF8)==SQLITE_OK ){
if( zRight && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK ){
sqlite3_soft_heap_limit64(N);
}
returnSingleInt(pParse, "soft_heap_limit", sqlite3_soft_heap_limit64(-1));

View File

@ -3331,9 +3331,11 @@ char sqlite3CompareAffinity(Expr *pExpr, char aff2);
int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
char sqlite3ExprAffinity(Expr *pExpr);
int sqlite3Atoi64(const char*, i64*, int, u8);
int sqlite3DecOrHexToI64(const char*, i64*);
void sqlite3Error(sqlite3*, int, const char*,...);
void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
u8 sqlite3HexToInt(int h);
int sqlite3HexToI64(const char*,i64*);
int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
#if defined(SQLITE_TEST)

View File

@ -255,22 +255,6 @@ int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){
return N<0 ? 0 : UpperToLower[*a] - UpperToLower[*b];
}
/*
** Translate a single byte of Hex into an integer.
** This routine only works if h really is a valid hexadecimal
** character: 0..9a..fA..F
*/
u8 sqlite3HexToInt(int h){
assert( (h>='0' && h<='9') || (h>='a' && h<='f') || (h>='A' && h<='F') );
#ifdef SQLITE_ASCII
h += 9*(1&(h>>6));
#endif
#ifdef SQLITE_EBCDIC
h += 9*(1&~(h>>4));
#endif
return (u8)(h & 0xf);
}
/*
** The string z[] is an text representation of a real number.
** Convert this string to a double and write it into *pResult.
@ -334,20 +318,6 @@ int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
}else if( *z=='+' ){
z+=incr;
}
#ifndef SQLITE_OMIT_HEX_INTEGER
else if( *z=='0'
&& &z[incr*2]<zEnd
&& (z[incr]=='x' || z[incr]=='X')
&& sqlite3Isxdigit(z[incr*2])
){
result = 0.0;
for(z += incr*2; z<zEnd && sqlite3Isxdigit(z[0]); z += incr){
result = result*16.0 + sqlite3HexToInt(z[0]);
}
*pResult = result;
return z>=zEnd && nonNum==0;
}
#endif
/* skip leading zeroes */
while( z<zEnd && z[0]=='0' ) z+=incr, nDigits++;
@ -506,7 +476,8 @@ static int compare2pow63(const char *zNum, int incr){
}
/*
** Convert zNum to a 64-bit signed integer.
** 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.
@ -551,21 +522,6 @@ int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
}else if( *zNum=='+' ){
zNum+=incr;
}
#ifndef SQLITE_OMIT_HEX_INTEGER
else if( *zNum=='0'
&& &zNum[incr*2]<zEnd
&& (zNum[incr]=='x' || zNum[incr]=='X')
&& sqlite3Isxdigit(zNum[incr*2])
){
zNum += incr*2;
while( zNum<zEnd && zNum[0]=='0' ) zNum += incr;
for(i=0; &zNum[i]<zEnd && sqlite3Isxdigit(zNum[i]); i+=incr){
u = u*16 + sqlite3HexToInt(zNum[i]);
}
memcpy(pNum, &u, 8);
return &zNum[i]<zEnd || i>16*incr || nonNum;
}
#endif
}
zStart = zNum;
while( zNum<zEnd && zNum[0]=='0' ){ zNum+=incr; } /* Skip leading zeros. */
@ -609,10 +565,44 @@ int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
}
}
/*
** Transform a UTF-8 integer literal, in either decimal or hexadecimal,
** into a 64-bit signed integer. This routine accepts hexadecimal literals,
** whereas sqlite3Atoi64() does not.
**
** 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
*/
int sqlite3DecOrHexToI64(const char *z, i64 *pOut){
#ifndef SQLITE_OMIT_HEX_INTEGER
if( z[0]=='0'
&& (z[1]=='x' || z[1]=='X')
&& sqlite3Isxdigit(z[2])
){
u64 u = 0;
int i, k;
for(i=2; z[i]=='0'; i++){}
for(k=i; sqlite3Isxdigit(z[k]); k++){
u = u*16 + sqlite3HexToInt(z[k]);
}
memcpy(pOut, &u, 8);
return (z[k]==0 && k-i<=16) ? 0 : 1;
}else
#endif /* SQLITE_OMIT_HEX_INTEGER */
{
return sqlite3Atoi64(z, pOut, sqlite3Strlen30(z), SQLITE_UTF8);
}
}
/*
** If zNum represents an integer that will fit in 32-bits, then set
** *pValue to that integer and return true. Otherwise return false.
**
** This routine accepts both decimal and hexadecimal notation for integers.
**
** Any non-numeric characters that following zNum are ignored.
** This is different from sqlite3Atoi64() which requires the
** input number to be zero-terminated.
@ -1091,6 +1081,24 @@ void sqlite3Put4byte(unsigned char *p, u32 v){
p[3] = (u8)v;
}
/*
** Translate a single byte of Hex into an integer.
** This routine only works if h really is a valid hexadecimal
** character: 0..9a..fA..F
*/
u8 sqlite3HexToInt(int h){
assert( (h>='0' && h<='9') || (h>='a' && h<='f') || (h>='A' && h<='F') );
#ifdef SQLITE_ASCII
h += 9*(1&(h>>6));
#endif
#ifdef SQLITE_EBCDIC
h += 9*(1&~(h>>4));
#endif
return (u8)(h & 0xf);
}
#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
/*
** Convert a BLOB literal of the form "x'hhhhhh'" into its binary

View File

@ -107,44 +107,22 @@ hexlit1 218 0x00E 14
hexlit1 219 0x00f 15
hexlit1 220 0x00F 15
proc hexlit2 {tnum hex ans} {
do_execsql_test hexlit-$tnum "SELECT printf('%7e',CAST('$hex' AS real))" $ans
}
# String literals that look like hex do not get cast or coerced.
#
do_execsql_test hexlit-300 {
CREATE TABLE t1(x INT, y REAL);
INSERT INTO t1 VALUES('1234','4567'),('0x1234','0x4567');
SELECT typeof(x), x, typeof(y), y, '#' FROM t1 ORDER BY rowid;
} {integer 1234 real 4567.0 # text 0x1234 text 0x4567 #}
do_execsql_test hexlit-301 {
SELECT CAST('0x1234' AS INTEGER);
} {0}
hexlit2 300 0x1 1.000000e+00
hexlit2 301 0x10 1.600000e+01
hexlit2 302 0x100 2.560000e+02
hexlit2 303 0x1000 4.096000e+03
hexlit2 304 0x10000 6.553600e+04
hexlit2 305 0x100000 1.048576e+06
hexlit2 306 0x1000000 1.677722e+07
hexlit2 307 0x10000000 2.684355e+08
hexlit2 308 0x100000000 4.294967e+09
hexlit2 309 0x1000000000 6.871948e+10
hexlit2 310 0x10000000000 1.099512e+12
hexlit2 311 0x100000000000 1.759219e+13
hexlit2 312 0x1000000000000 2.814750e+14
hexlit2 313 0x10000000000000 4.503600e+15
hexlit2 314 0x100000000000000 7.205759e+16
hexlit2 315 0x1000000000000000 1.152922e+18
hexlit2 316 0x10000000000000000 1.844674e+19
hexlit2 317 0x100000000000000000 2.951479e+20
hexlit2 318 0x1000000000000000000 4.722366e+21
hexlit2 319 0x10000000000000000000 7.555786e+22
hexlit2 320 0x100000000000000000000 1.208926e+24
hexlit2 321 0x1000000000000000000000 1.934281e+25
hexlit2 322 0x10000000000000000000000 3.094850e+26
hexlit2 323 0x100000000000000000000000 4.951760e+27
hexlit2 324 0x1000000000000000000000000 7.922816e+28
hexlit2 325 0x10000000000000000000000000 1.267651e+30
hexlit2 326 0x100000000000000000000000000 2.028241e+31
hexlit2 327 0x1000000000000000000000000000 3.245186e+32
hexlit2 328 0x10000000000000000000000000000 5.192297e+33
hexlit2 329 0x100000000000000000000000000000 8.307675e+34
# Oversized hex literals are rejected
#
do_catchsql_test hexlist-400 {
SELECT 0x10000000000000000;
} {1 {hex literal too big: 0x10000000000000000}}
hexlit2 400 0x07fffffffffffffff 9.223372e+18
hexlit2 401 0x08000000000000000 9.223372e+18
hexlit2 402 0x0ffffffffffffffff 1.844674e+19
hexlit2 403 0x10000000000000000 1.844674e+19
finish_test