]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Factor out the logic that does quoting for the SQL quote() function, so that
authordrh <>
Fri, 10 Dec 2021 21:01:24 +0000 (21:01 +0000)
committerdrh <>
Fri, 10 Dec 2021 21:01:24 +0000 (21:01 +0000)
it might be reused for other purposes.

FossilOrigin-Name: 8e98ba1eeb1a5a61b7cb2de337ef8bca3d07494266a50d62b9c6bc60ad0a955f

manifest
manifest.uuid
src/func.c
src/printf.c
src/sqliteInt.h

index 2c5dc8afefdb33526e3d44bb6d71b92af4e27ece..fdf5374107cab291f4417af105844cd5286bf9e2 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Rename\sthe\sinternal\sroutine\sconstructBloomFilter()\sto\nsqlite3ConstructBloomFilter().\sOSSFuzz\sis\sreporting\sa\scrash\swith\sa\sgarbled\nstack\sthat\swe\scannot\sreproduce.\sPerhaps\sthe\soriginal\s"constructBloomFilter()"\nname\sis\scolliding\swith\ssome\sinternal\sname\sused\sby\sOSSFuzz.\sWe'll\ssee\sif\sthis\nrename\sclears\sthe\sproblem.
-D 2021-12-10T17:36:16.695
+C Factor\sout\sthe\slogic\sthat\sdoes\squoting\sfor\sthe\sSQL\squote()\sfunction,\sso\sthat\nit\smight\sbe\sreused\sfor\sother\spurposes.
+D 2021-12-10T21:01:24.675
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -506,7 +506,7 @@ F src/delete.c 19814f621cde10b1771a0dea7fe25d3d7d39975b8d4be4888537d30860e7c08c
 F src/expr.c 827179c78d2ca7cc318392811de8151c60eacf7ce804b13e61bb7ef38f954846
 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
 F src/fkey.c 187b67af20c5795953a592832c5d985e4313fe503ebd8f95e3e9e9ad5a730bb5
-F src/func.c 1cfb09d7ffca81238eccefdb0293e1f5b7cfebbd1816dfad5ec6024742a7496b
+F src/func.c 0f576a0c102485676266e63a796223e63c3cdb04baf3678ccc8bfeedba4a6fd4
 F src/global.c 1f56aead86e8a18c4415638f5e6c4d0a0550427f4b3f5d065ba5164cc09c22e8
 F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19
 F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
@@ -547,7 +547,7 @@ F src/pcache1.c 54881292a9a5db202b2c0ac541c5e3ef9a5e8c4f1c1383adb2601d5499a60e65
 F src/pragma.c c536665ce8431c8b1efbf7e0a5c01852f49f7bf28f1954f8118b2d28e4a3797f
 F src/pragma.h 87330ed2fbfa2a1274de93ca0ab850fba336189228cb256089202c3b52766fad
 F src/prepare.c 40961a1170a4c4151a90dae29dd00fc6c155f1af8246abeeeb8f0a10b3fb9719
-F src/printf.c 5901672228f305f7d493cbc4e7d76a61a5caecdbc1cd06b1f9ec42ea4265cf8d
+F src/printf.c 9565aeb5af5376fd23c993b8da1ac37008fad65435a703316eef9f41229f702d
 F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c
 F src/resolve.c 4a1db4aadd802683db40ca2dbbb268187bd195f10cbdb7206dbd8ac988795571
 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
@@ -556,7 +556,7 @@ F src/shell.c.in 239bee1085d94964f02582b0714dc3fc85cfc16e27e95813e4dbc24bb215a7e
 F src/sqlite.h.in 5999d6db0e65afbd686b76cddc385b310aa3815624edba43987913067f50e209
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h 8ff2fd2c166150b2e48639f5e506fb44e29f1a3f65031710b9e89d1c126ac839
-F src/sqliteInt.h b4391c3c2ae0a8020ce0f543fc2b529f9bcdf72ab7ba3c31d170e3228169162f
+F src/sqliteInt.h e7dd69a85c53461c937d50c97f8efd9761b14f9bcfb63450809e85c100c08538
 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@@ -1934,7 +1934,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 633bfeeea2bccdd44126acf3f61ecca163c9d933bdc787a2c18a697dc9406882
-R 2727e42f3726d0bce34928653c056def
+P 403e7312dd9a3fe493a21aceb82e387d6f152622d66c1b403c881597713e8cc3
+R 4fa3f8129d17f257f0557369c327b148
 U drh
-Z 81c6addbec75f6f350e0d3032a7fdc73
+Z 1eec60e7fbec94682a3271bf749ce5cf
index 5b54a326b3a0b65db4e8fc53b7b600e00d9fed67..579ae8fcd8e42c54285135a65bba578aa60ae454 100644 (file)
@@ -1 +1 @@
-403e7312dd9a3fe493a21aceb82e387d6f152622d66c1b403c881597713e8cc3
\ No newline at end of file
+8e98ba1eeb1a5a61b7cb2de337ef8bca3d07494266a50d62b9c6bc60ad0a955f
\ No newline at end of file
index 6a2903d328b5ac3fa1941366ebca2e0901f7c62f..eeab1d26475c6542154bc7c0ef042e99bbabcb8f 100644 (file)
@@ -1027,39 +1027,42 @@ static const char hexdigits[] = {
 };
 
 /*
-** Implementation of the QUOTE() function.  This function takes a single
-** argument.  If the argument is numeric, the return value is the same as
-** the argument.  If the argument is NULL, the return value is the string
-** "NULL".  Otherwise, the argument is enclosed in single quotes with
-** single-quote escapes.
+** Append to pStr text that is the SQL literal representation of the
+** value contained in pValue.
 */
-static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
-  assert( argc==1 );
-  UNUSED_PARAMETER(argc);
-  switch( sqlite3_value_type(argv[0]) ){
+void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue){
+  /* As currently implemented, the string must be initially empty.
+  ** we might relax this requirement in the future, but that will
+  ** require enhancements to the implementation. */
+  assert( pStr!=0 && pStr->nChar==0 );
+
+  switch( sqlite3_value_type(pValue) ){
     case SQLITE_FLOAT: {
       double r1, r2;
-      char zBuf[50];
-      r1 = sqlite3_value_double(argv[0]);
-      sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.15g", r1);
-      sqlite3AtoF(zBuf, &r2, 20, SQLITE_UTF8);
-      if( r1!=r2 ){
-        sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.20e", r1);
+      const char *zVal;
+      r1 = sqlite3_value_double(pValue);
+      sqlite3_str_appendf(pStr, "%!.15g", r1);
+      zVal = sqlite3_str_value(pStr);
+      if( zVal ){
+        sqlite3AtoF(zVal, &r2, pStr->nChar, SQLITE_UTF8);
+        if( r1!=r2 ){
+          sqlite3_str_reset(pStr);
+          sqlite3_str_appendf(pStr, "%!.20e", r1);
+        }
       }
-      sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
       break;
     }
     case SQLITE_INTEGER: {
-      sqlite3_result_value(context, argv[0]);
+      sqlite3_str_appendf(pStr, "%lld", sqlite3_value_int64(pValue));
       break;
     }
     case SQLITE_BLOB: {
-      char *zText = 0;
-      char const *zBlob = sqlite3_value_blob(argv[0]);
-      int nBlob = sqlite3_value_bytes(argv[0]);
-      assert( zBlob==sqlite3_value_blob(argv[0]) ); /* No encoding change */
-      zText = (char *)contextMalloc(context, (2*(i64)nBlob)+4); 
-      if( zText ){
+      char const *zBlob = sqlite3_value_blob(pValue);
+      int nBlob = sqlite3_value_bytes(pValue);
+      assert( zBlob==sqlite3_value_blob(pValue) ); /* No encoding change */
+      sqlite3StrAccumEnlarge(pStr, nBlob*2 + 4);
+      if( pStr->accError==0 ){
+        char *zText = pStr->zText;
         int i;
         for(i=0; i<nBlob; i++){
           zText[(i*2)+2] = hexdigits[(zBlob[i]>>4)&0x0F];
@@ -1069,42 +1072,47 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
         zText[(nBlob*2)+3] = '\0';
         zText[0] = 'X';
         zText[1] = '\'';
-        sqlite3_result_text(context, zText, -1, SQLITE_TRANSIENT);
-        sqlite3_free(zText);
+        pStr->nChar = nBlob*2 + 3;
       }
       break;
     }
     case SQLITE_TEXT: {
-      int i,j;
-      u64 n;
-      const unsigned char *zArg = sqlite3_value_text(argv[0]);
-      char *z;
-
-      if( zArg==0 ) return;
-      for(i=0, n=0; zArg[i]; i++){ if( zArg[i]=='\'' ) n++; }
-      z = contextMalloc(context, ((i64)i)+((i64)n)+3);
-      if( z ){
-        z[0] = '\'';
-        for(i=0, j=1; zArg[i]; i++){
-          z[j++] = zArg[i];
-          if( zArg[i]=='\'' ){
-            z[j++] = '\'';
-          }
-        }
-        z[j++] = '\'';
-        z[j] = 0;
-        sqlite3_result_text(context, z, j, sqlite3_free);
-      }
+      const unsigned char *zArg = sqlite3_value_text(pValue);
+      sqlite3_str_appendf(pStr, "%Q", zArg);
       break;
     }
     default: {
-      assert( sqlite3_value_type(argv[0])==SQLITE_NULL );
-      sqlite3_result_text(context, "NULL", 4, SQLITE_STATIC);
+      assert( sqlite3_value_type(pValue)==SQLITE_NULL );
+      sqlite3_str_append(pStr, "NULL", 4);
       break;
     }
   }
 }
 
+/*
+** Implementation of the QUOTE() function.  
+**
+** The quote(X) function returns the text of an SQL literal which is the
+** value of its argument suitable for inclusion into an SQL statement.
+** Strings are surrounded by single-quotes with escapes on interior quotes
+** as needed. BLOBs are encoded as hexadecimal literals. Strings with
+** embedded NUL characters cannot be represented as string literals in SQL
+** and hence the returned string literal is truncated prior to the first NUL.
+*/
+static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
+  sqlite3_str str;
+  sqlite3 *db = sqlite3_context_db_handle(context);
+  assert( argc==1 );
+  UNUSED_PARAMETER(argc);
+  sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
+  sqlite3QuoteValue(&str,argv[0]);
+  sqlite3_result_text(context, sqlite3StrAccumFinish(&str), str.nChar,
+                      SQLITE_DYNAMIC);
+  if( str.accError==SQLITE_NOMEM ){
+    sqlite3_result_error_nomem(context);
+  }
+}
+
 /*
 ** The unicode() function.  Return the integer unicode code-point value
 ** for the first character of the input string. 
index e63518450c98f3850b4043030cc1d03e871164ad..6128e5cb4c69afcf68764669777e1611c0efc720 100644 (file)
@@ -916,7 +916,7 @@ void sqlite3_str_vappendf(
 ** Return the number of bytes of text that StrAccum is able to accept
 ** after the attempted enlargement.  The value returned might be zero.
 */
-static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
+int sqlite3StrAccumEnlarge(StrAccum *p, int N){
   char *zNew;
   assert( p->nChar+(i64)N >= p->nAlloc ); /* Only called if really needed */
   if( p->accError ){
index bd02e2626f29599c30d5623fe571a4f404cbbac1..48a94a7b33922419a989c9b369372f51b705591b 100644 (file)
@@ -4684,6 +4684,7 @@ Select *sqlite3SelectDup(sqlite3*,const Select*,int);
 FuncDef *sqlite3FunctionSearch(int,const char*);
 void sqlite3InsertBuiltinFuncs(FuncDef*,int);
 FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,u8,u8);
+void sqlite3QuoteValue(StrAccum*,sqlite3_value*);
 void sqlite3RegisterBuiltinFunctions(void);
 void sqlite3RegisterDateTimeFunctions(void);
 void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3*);
@@ -4970,6 +4971,7 @@ int sqlite3ApiExit(sqlite3 *db, int);
 int sqlite3OpenTempDatabase(Parse *);
 
 void sqlite3StrAccumInit(StrAccum*, sqlite3*, char*, int, int);
+int sqlite3StrAccumEnlarge(StrAccum*, int);
 char *sqlite3StrAccumFinish(StrAccum*);
 void sqlite3StrAccumSetError(StrAccum*, u8);
 void sqlite3ResultStrAccum(sqlite3_context*,StrAccum*);