]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Handle malloc() failures that occur inside create_collation() calls. (CVS 2966)
authordanielk1977 <danielk1977@noemail.net>
Wed, 18 Jan 2006 04:26:07 +0000 (04:26 +0000)
committerdanielk1977 <danielk1977@noemail.net>
Wed, 18 Jan 2006 04:26:07 +0000 (04:26 +0000)
FossilOrigin-Name: 95c5903f368413019af83aa73263e0e9d1204b62

manifest
manifest.uuid
src/main.c
src/test1.c
test/malloc.test

index f3f3576643bcf1cffdc8598eb445d4bb52dc9442..6cc0214f495ed10029dc09c857cffac9aacbae7a 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Arrange\sfor\sThreadData\sto\sbe\sautomatically\sdeallocated\seven\sif\sSQLITE_MEMDEBUG\sis\sdefined.\sFix\sfor\s#1623.\s(CVS\s2965)
-D 2006-01-17T16:10:14
+C Handle\smalloc()\sfailures\sthat\soccur\sinside\screate_collation()\scalls.\s(CVS\s2966)
+D 2006-01-18T04:26:07
 F Makefile.in ab3ffd8d469cef4477257169b82810030a6bb967
 F Makefile.linux-gcc aee18d8a05546dcf1888bd4547e442008a49a092
 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@@ -48,7 +48,7 @@ F src/hash.c 8747cf51d12de46512880dfcf1b68b4e24072863
 F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84
 F src/insert.c a5595cf8d1d8ba087b676a63f1f7277ea44b5ac1
 F src/legacy.c 9bf7ee1b63c99aac6669533986a5240b16101458
-F src/main.c e934ce6ce3b7166ad98c2778160f865761196480
+F src/main.c bab16cf13d9a6388c321f6bc4693d258aea80a2a
 F src/md5.c c5fdfa5c2593eaee2e32a5ce6c6927c986eaf217
 F src/os.c 1d1a61cdf150e9f9520a3bc787c8465148ea2e78
 F src/os.h 9debc3d3ca4cdafde222a0ea74a4c8415aef4f22
@@ -73,7 +73,7 @@ F src/sqlite.h.in 492580f7e3ff71eb43193eb7bb98e2d549889ce3
 F src/sqliteInt.h d7b20e0a9453db123809d0bcc46d6ae0e4cf6bca
 F src/table.c 486dcfce532685b53b5a2b5da8bba0ded6fb2316
 F src/tclsqlite.c d650bea0248fc0a310ddc2cb94273a3a5021fddf
-F src/test1.c 4dccd51f786f24d8f947f1028d840ab35f46d4de
+F src/test1.c deb48cd5ab369a2ffccb62b017d248188a3be201
 F src/test2.c ca74a1d8aeb7d9606e8f6b762c5daf85c1a3f92b
 F src/test3.c 9742aa146eb750cab81c1d5605286c3a0eb88054
 F src/test4.c 6633cb7b4a7429e938804a34f688d118c8b7f8e1
@@ -186,7 +186,7 @@ F test/lock.test 9b7afcb24f53d24da502abb33daaad2cd6d44107
 F test/lock2.test d83ba79d3c4fffdb5b926c7d8ca7a36c34288a55
 F test/lock3.test 615111293cf32aa2ed16d01c6611737651c96fb9
 F test/main.test b12f01d49a5c805a33fa6c0ef168691f63056e79
-F test/malloc.test 34c2c0ce7f45bc5fe2f7f3c0b911e505af66e27f
+F test/malloc.test 095d23a3840549cfc4282f95d9dc531152473c05
 F test/malloc2.test e6e321db96d6c94cb18bf82ad7215070c41e624e
 F test/malloc3.test 265644c655497242f7c0a1bb5b36c8500a5fc27c
 F test/malloc4.test 2e29d155eb4b4808019ef47eeedfcbe9e09e0f05
@@ -341,7 +341,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b
 F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
-P 62dd2427784721436737a6e8e11fc05e10f0c44d
-R 394c8b76a3f1fd5dd680d2c15b203185
+P 9e2e40845d30cc150abe23ee318a721b4fe9613c
+R 07ad42513a6cd0f560889373df73f012
 U danielk1977
-Z 4cce626803e4e936d7ee616c54ded64d
+Z 7bf4533c1b6879283691c3482fcc8f38
index cfa639532d67f07c9730da2683bfcc985911840d..608f9796561e27b3c09e1356c3c60d399b3fa8dd 100644 (file)
@@ -1 +1 @@
-9e2e40845d30cc150abe23ee318a721b4fe9613c
\ No newline at end of file
+95c5903f368413019af83aa73263e0e9d1204b62
\ No newline at end of file
index 6ceea4b44a536e57e49675836baf8b4b84ca2506..59e524a3dc06c21e662329b95c9619c5231ea79b 100644 (file)
@@ -14,7 +14,7 @@
 ** other files are for internal use by SQLite and should not be
 ** accessed by users of the library.
 **
-** $Id: main.c,v 1.324 2006/01/17 13:21:40 danielk1977 Exp $
+** $Id: main.c,v 1.325 2006/01/18 04:26:07 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -745,6 +745,60 @@ int sqlite3_errcode(sqlite3 *db){
   return db->errCode;
 }
 
+static int createCollation(
+  sqlite3* db, 
+  const char *zName, 
+  int enc, 
+  void* pCtx,
+  int(*xCompare)(void*,int,const void*,int,const void*)
+){
+  CollSeq *pColl;
+  
+  if( sqlite3SafetyCheck(db) ){
+    return SQLITE_MISUSE;
+  }
+
+  /* If SQLITE_UTF16 is specified as the encoding type, transform this
+  ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the
+  ** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally.
+  */
+  if( enc==SQLITE_UTF16 ){
+    enc = SQLITE_UTF16NATIVE;
+  }
+
+  if( enc!=SQLITE_UTF8 && enc!=SQLITE_UTF16LE && enc!=SQLITE_UTF16BE ){
+    sqlite3Error(db, SQLITE_ERROR, 
+        "Param 3 to sqlite3_create_collation() must be one of "
+        "SQLITE_UTF8, SQLITE_UTF16, SQLITE_UTF16LE or SQLITE_UTF16BE"
+    );
+    return SQLITE_ERROR;
+  }
+
+  /* Check if this call is removing or replacing an existing collation 
+  ** sequence. If so, and there are active VMs, return busy. If there
+  ** are no active VMs, invalidate any pre-compiled statements.
+  */
+  pColl = sqlite3FindCollSeq(db, (u8)enc, zName, strlen(zName), 0);
+  if( pColl && pColl->xCmp ){
+    if( db->activeVdbeCnt ){
+      sqlite3Error(db, SQLITE_BUSY, 
+        "Unable to delete/modify collation sequence due to active statements");
+      return SQLITE_BUSY;
+    }
+    sqlite3ExpirePreparedStatements(db);
+  }
+
+  pColl = sqlite3FindCollSeq(db, (u8)enc, zName, strlen(zName), 1);
+  if( pColl ){
+    pColl->xCmp = xCompare;
+    pColl->pUser = pCtx;
+    pColl->enc = enc;
+  }
+  sqlite3Error(db, SQLITE_OK, 0);
+  return SQLITE_OK;
+}
+
+
 /*
 ** This routine does the work of opening a database on behalf of
 ** sqlite3_open() and sqlite3_open16(). The database filename "zFilename"  
@@ -776,8 +830,8 @@ static int openDatabase(
   ** and UTF-16, so add a version for each to avoid any unnecessary
   ** conversions. The only error that can occur here is a malloc() failure.
   */
-  if( sqlite3_create_collation(db, "BINARY", SQLITE_UTF8, 0,binCollFunc) ||
-      sqlite3_create_collation(db, "BINARY", SQLITE_UTF16, 0,binCollFunc) ||
+  if( createCollation(db, "BINARY", SQLITE_UTF8, 0,binCollFunc) ||
+      createCollation(db, "BINARY", SQLITE_UTF16, 0,binCollFunc) ||
       (db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 6, 0))==0 
   ){
     /* sqlite3_create_collation() is an external API. So the mallocFailed flag
@@ -789,7 +843,7 @@ static int openDatabase(
   }
 
   /* Also add a UTF-8 case-insensitive collation sequence. */
-  sqlite3_create_collation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc);
+  createCollation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc);
 
   /* Set flags on the built-in collating sequences */
   db->pDfltColl->type = SQLITE_COLL_BINARY;
@@ -935,52 +989,14 @@ int sqlite3_create_collation(
   void* pCtx,
   int(*xCompare)(void*,int,const void*,int,const void*)
 ){
-  CollSeq *pColl;
-  int rc = SQLITE_OK;
-  
-  if( sqlite3SafetyCheck(db) ){
-    return SQLITE_MISUSE;
-  }
-
-  /* If SQLITE_UTF16 is specified as the encoding type, transform this
-  ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the
-  ** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally.
-  */
-  if( enc==SQLITE_UTF16 ){
-    enc = SQLITE_UTF16NATIVE;
-  }
-
-  if( enc!=SQLITE_UTF8 && enc!=SQLITE_UTF16LE && enc!=SQLITE_UTF16BE ){
-    sqlite3Error(db, SQLITE_ERROR, 
-        "Param 3 to sqlite3_create_collation() must be one of "
-        "SQLITE_UTF8, SQLITE_UTF16, SQLITE_UTF16LE or SQLITE_UTF16BE"
-    );
-    return SQLITE_ERROR;
-  }
-
-  /* Check if this call is removing or replacing an existing collation 
-  ** sequence. If so, and there are active VMs, return busy. If there
-  ** are no active VMs, invalidate any pre-compiled statements.
-  */
-  pColl = sqlite3FindCollSeq(db, (u8)enc, zName, strlen(zName), 0);
-  if( pColl && pColl->xCmp ){
-    if( db->activeVdbeCnt ){
-      sqlite3Error(db, SQLITE_BUSY, 
-        "Unable to delete/modify collation sequence due to active statements");
-      return SQLITE_BUSY;
-    }
-    sqlite3ExpirePreparedStatements(db);
-  }
-
-  pColl = sqlite3FindCollSeq(db, (u8)enc, zName, strlen(zName), 1);
-  if( 0==pColl ){
+  int rc;
+  assert( !sqlite3ThreadDataReadOnly()->mallocFailed );
+  rc = createCollation(db, zName, enc, pCtx, xCompare);
+  if( sqlite3ThreadDataReadOnly()->mallocFailed ){
+    sqlite3MallocClearFailed();
     rc = SQLITE_NOMEM;
-  }else{
-    pColl->xCmp = xCompare;
-    pColl->pUser = pCtx;
-    pColl->enc = enc;
+    sqlite3Error(db, rc, 0);
   }
-  sqlite3Error(db, rc, 0);
   return rc;
 }
 
@@ -995,14 +1011,19 @@ int sqlite3_create_collation16(
   void* pCtx,
   int(*xCompare)(void*,int,const void*,int,const void*)
 ){
-  char *zName8;
-  int rc;
-  if( sqlite3SafetyCheck(db) ){
-    return SQLITE_MISUSE;
-  }
+  int rc = SQLITE_OK;
+  char *zName8; 
+  assert( !sqlite3ThreadDataReadOnly()->mallocFailed );
   zName8 = sqlite3utf16to8(zName, -1);
-  rc = sqlite3_create_collation(db, zName8, enc, pCtx, xCompare);
-  sqliteFree(zName8);
+  if( zName8 ){
+    rc = createCollation(db, zName8, enc, pCtx, xCompare);
+    sqliteFree(zName8);
+  }
+  if( sqlite3ThreadDataReadOnly()->mallocFailed ){
+    sqlite3MallocClearFailed();
+    rc = SQLITE_NOMEM;
+    sqlite3Error(db, rc, 0);
+  }
   return rc;
 }
 #endif /* SQLITE_OMIT_UTF16 */
index 2d6f2727ea7e56a51e6afd36ee6483989d3f1d49..d211ee39eed969ed7166a2eed05f783f1a74cee1 100644 (file)
@@ -13,7 +13,7 @@
 ** is not included in the SQLite library.  It is used for automated
 ** testing of the SQLite library.
 **
-** $Id: test1.c,v 1.193 2006/01/17 13:21:40 danielk1977 Exp $
+** $Id: test1.c,v 1.194 2006/01/18 04:26:07 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include "tcl.h"
@@ -1346,13 +1346,24 @@ static int test_collate(
             (void *)SQLITE_UTF16LE, val?test_collate_func:0);
     if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
 
+#ifdef SQLITE_MEMDEBUG
+    if( sqlite3_iMallocFail>0 ){
+      sqlite3_iMallocFail++;
+    }
+#endif
     pVal = sqlite3ValueNew();
     sqlite3ValueSetStr(pVal, -1, "test_collate", SQLITE_UTF8, SQLITE_STATIC);
-    sqlite3_create_collation16(db, sqlite3ValueText(pVal, SQLITE_UTF16NATIVE), 
-          SQLITE_UTF16BE, (void *)SQLITE_UTF16BE, val?test_collate_func:0);
+    rc = sqlite3_create_collation16(db, 
+          sqlite3ValueText(pVal, SQLITE_UTF16NATIVE), SQLITE_UTF16BE, 
+          (void *)SQLITE_UTF16BE, val?test_collate_func:0);
     sqlite3ValueFree(pVal);
   }
   if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
+  
+  if( rc!=SQLITE_OK ){
+    Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
+    return TCL_ERROR;
+  }
   return TCL_OK;
 
 bad_args:
index 726bc3297bd97349ae007259ee1614d413c5d9d9..ff934911f9756643b0376b9b4463ae1ee7dbf530 100644 (file)
@@ -14,7 +14,7 @@
 # special feature is used to see what happens in the library if a malloc
 # were to really fail due to an out-of-memory situation.
 #
-# $Id: malloc.test,v 1.27 2006/01/17 13:21:40 danielk1977 Exp $
+# $Id: malloc.test,v 1.28 2006/01/18 04:26:08 danielk1977 Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -97,7 +97,11 @@ proc do_malloc_test {tn args} {
       if {$leftover>0} {
         if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v  Message=$msg"}
         set ::go 0
-        set v {1 1}
+        if {$v} {
+          puts "\nError message returned: $msg"
+        } else {
+          set v {1 1}
+        }
       } else {
         set v2 [expr {$msg=="" || $msg=="out of memory"}]
         if {!$v2} {puts "\nError message returned: $msg"}
@@ -363,25 +367,44 @@ ifcapable crashtest {
 }
 
 if {$tcl_platform(platform)!="windows"} {
-do_malloc_test 14 -tclprep {
-  catch {db close}
-  sqlite3 db2 test2.db
-  db2 eval {
-    PRAGMA synchronous = 0;
-    CREATE TABLE t1(a, b);
-    INSERT INTO t1 VALUES(1, 2);
-    BEGIN;
-    INSERT INTO t1 VALUES(3, 4);
+  do_malloc_test 14 -tclprep {
+    catch {db close}
+    sqlite3 db2 test2.db
+    db2 eval {
+      PRAGMA synchronous = 0;
+      CREATE TABLE t1(a, b);
+      INSERT INTO t1 VALUES(1, 2);
+      BEGIN;
+      INSERT INTO t1 VALUES(3, 4);
+    }
+    copy_file test2.db test.db
+    copy_file test2.db-journal test.db-journal
+    db2 close
+  } -tclbody {
+    sqlite3 db test.db
+    db eval {
+      SELECT * FROM t1;
+    }  
   }
-  copy_file test2.db test.db
-  copy_file test2.db-journal test.db-journal
-  db2 close
-} -tclbody {
-  sqlite3 db test.db
-  db eval {
-    SELECT * FROM t1;
-  }  
 }
+
+proc string_compare {a b} {
+  return [string compare $a $b]
+}
+
+# Test for malloc() failures in sqlite3_create_collation() and 
+# sqlite3_create_collation16().
+do_malloc_test 15 -tclbody {
+  db collate string_compare string_compare
+  if {[catch {add_test_collate $::DB 1 1 1} msg]} {
+    if {$msg=="SQLITE_NOMEM"} {set msg "out of memory"}
+    error $msg
+  }
+  execsql {
+    CREATE TABLE t1(a, b COLLATE string_compare);
+    INSERT INTO t1 VALUES(10, 'string');
+    INSERT INTO t1 VALUES(10, 'string2');
+  }
 }
 
 # Ensure that no file descriptors were leaked.