]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Change the hex literal processing so that only the SQL parser understands
authordrh <drh@noemail.net>
Wed, 23 Jul 2014 13:40:49 +0000 (13:40 +0000)
committerdrh <drh@noemail.net>
Wed, 23 Jul 2014 13:40:49 +0000 (13:40 +0000)
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

manifest
manifest.uuid
src/expr.c
src/main.c
src/pragma.c
src/sqliteInt.h
src/util.c
test/hexlit.test

index 656415a5998af74ae51d7c651b0a18316cf5dc38..8a6aa1f09915c0881bb07bb9522cebe28bd8ed59 100644 (file)
--- a/manifest
+++ b/manifest
@@ -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
index 4442ea274c775bebb7cac5f78e4b94d0f486ec4a..f47a66e629264d7315289bbaac2a771148b141b9 100644 (file)
@@ -1 +1 @@
-4b86ccdf4f4eb4339a5706e10ad24f01b6c3939e
\ No newline at end of file
+6c6f0de59bf96b79c8ace8c9bfe48c7a6a306a50
\ No newline at end of file
index 803d93f30dd0524a872013be90567df0dbb3dd13..a60c0cba4350b3d67e3a2e812baedc7ff5ba0398 100644 (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
-      codeReal(v, z, negFlag, iMem);
+      if( sqlite3_strnicmp(z,"0x",2)==0 ){
+        sqlite3ErrorMsg(pParse, "hex literal too big: %s", z);
+      }else{
+        codeReal(v, z, negFlag, iMem);
+      }
 #endif
     }
   }
index 5e976e3397a88686573784b6d8c367458aa7f743..904e0a4fc1aefc1df96abfbd37a75a2ee840da51 100644 (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;
index 4c69ceb4fd63a7e4609718e7e3c3ac0035a3d0a0..709662c9897e7fa86fb109eb7c2398c38e8bba4a 100644 (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));
index 7edc04ca42efb01cfef74e02cc1363b29d267216..0bbf9945cef40f60f91c914a1edf3169be7a4c65 100644 (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) 
index f7f3f58b2bb9835e51f3cc65d9dd7c3e4793c737..619af7f758e05571631728d81b695ec09d94b068 100644 (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
index 39ddf96e0b3cbbc054d64384f330e2468cd2fd56..41133aba0ff8f19f7b8ba7d27be47fedc8782bda 100644 (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