From 00fd957b789c64f143b48eaba0c33376b61db56d Mon Sep 17 00:00:00 2001 From: danielk1977 Date: Wed, 7 Dec 2005 06:27:43 +0000 Subject: [PATCH] Add some tests for malloc() failure within the column_name() and column_decl() APIs. (CVS 2805) FossilOrigin-Name: 78f10ca0a6a02e9e8e6811489841a19e213f3afb --- manifest | 23 +++++----- manifest.uuid | 2 +- src/tclsqlite.c | 14 +++--- src/vdbeapi.c | 11 ++++- src/vdbemem.c | 13 +++++- src/where.c | 4 +- test/malloc3.test | 8 +++- test/malloc4.test | 114 ++++++++++++++++++++++++++++++++++++++++++++++ test/quick.test | 8 ++-- 9 files changed, 166 insertions(+), 31 deletions(-) create mode 100644 test/malloc4.test diff --git a/manifest b/manifest index b33dbc8d55..cfb8ccc3d4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Allow\sVACUUM\sto\sdetach\sthe\sauxillary\sdatabase\safter\smalloc()\sfails.\s(CVS\s2804) -D 2005-12-06T17:48:32 +C Add\ssome\stests\sfor\smalloc()\sfailure\swithin\sthe\scolumn_name()\sand\scolumn_decl()\sAPIs.\s(CVS\s2805) +D 2005-12-07T06:27:44 F Makefile.in e3c6b3a38d734d41574c04f2fc90d18de2b87102 F Makefile.linux-gcc aee18d8a05546dcf1888bd4547e442008a49a092 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -71,7 +71,7 @@ F src/shell.c 3596c1e559b82663057940d19ba533ad421c7dd3 F src/sqlite.h.in 8e648e1f386e4509f2f96c09ded7c07b0df0c9a2 F src/sqliteInt.h bbc310a83a32476aa960055a166af4a0ef503a79 F src/table.c 486dcfce532685b53b5a2b5da8bba0ded6fb2316 -F src/tclsqlite.c a497c3adfd2c85da6a934331ec0041e47884fbcb +F src/tclsqlite.c 328060916c24d328cfab1622c9a0e7ad57c2da8c F src/test1.c 0b4bf8ab9afb37f34a83c46f81de54adf519b23d F src/test2.c 36390cdfc70c08e5ee0b466d0654a117f398bbff F src/test3.c f4e6a16a602091696619a1171bda25c0e3df49f7 @@ -87,11 +87,11 @@ F src/vacuum.c 4d64ce98a4cb130002cbf8aba018b2567773e6b1 F src/vdbe.c 7f4a2affee140b7b57952ab2c081a9c22b950638 F src/vdbe.h 8729a4ee16ff9aeab2af9667df3cf300ff978e13 F src/vdbeInt.h 0055c37eccbf3a189fd893a90f8eb6a5fa60c871 -F src/vdbeapi.c 4fd33e87aa6cbd77e59da142e1df67ec0430225f +F src/vdbeapi.c b80b3a1e8bf7866d96ca76d91bba979155bace57 F src/vdbeaux.c 90143aaffbe232a700fd05e4b2e7428d512b605b F src/vdbefifo.c 9efb94c8c3f4c979ebd0028219483f88e57584f5 -F src/vdbemem.c cd9609c1e7f71ec76d9840c84c3a57ebfa6539cf -F src/where.c c0882f2d42e636f78fb45b9279e2739d4291e6ab +F src/vdbemem.c 1c70555d615c6001c4490dedb6a62cb2884b92ff +F src/where.c 269569f380ddc018518f67765fe2f0d3c8760e28 F tclinstaller.tcl 046e3624671962dc50f0481d7c25b38ef803eb42 F test/all.test 7f0988442ab811dfa41793b5b550f5828ce316f3 F test/alter.test 9d6837a3d946b73df692b7cef2a7644d2e2f6bc6 @@ -179,7 +179,8 @@ F test/lock3.test 615111293cf32aa2ed16d01c6611737651c96fb9 F test/main.test b12f01d49a5c805a33fa6c0ef168691f63056e79 F test/malloc.test a5ed721cf7d1b12602ede4f98c11b65ab1582cc0 F test/malloc2.test e6e321db96d6c94cb18bf82ad7215070c41e624e -F test/malloc3.test 1c7eebb2cf0f1fb1fbcaa1d6b3f25767c55aa6c9 +F test/malloc3.test 0d60a9d19196581e9279c2d040bebd8162ab495b +F test/malloc4.test 593ae91bf69ab5abc68f7652e679e5d207e23166 F test/manydb.test d81debbf5871242e3b5df1d3bb5e14c50431b6f8 F test/memdb.test 1860e060be810bf0775bc57408a5b7c4954bcaea F test/memleak.test df2b2b96e77f8ba159a332299535b1e5f18e49ac @@ -199,7 +200,7 @@ F test/pagesize.test cbc6a312b6f6c0f02619b189985df2a14164b690 F test/pragma.test 95ea907adf68459e1be6f310c9ae94d1d59c465b F test/printf.test 9e10c74e16bf889f8495ddb3d6f5f891e75ff1b7 F test/progress.test 16496001da445e6534afb94562c286708316d82f x -F test/quick.test a94d12658a2b590c1a5be580bef09bbb04c1266b +F test/quick.test 84138c0fcc959a5e7761625aa52d37d55e56b748 F test/quote.test 5891f2338980916cf7415484b4ce785294044adb F test/reindex.test 38b138abe36bf9a08c791ed44d9f76cd6b97b78b F test/rollback.test 94cd981ee3a627d9f6466f69dcf1f7dbfe695d7a @@ -325,7 +326,7 @@ F www/tclsqlite.tcl ddcf912ea48695603c8ed7efb29f0812ef8d1b49 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513 -P 5e04ec694add7a8331e3d6fbdfcaed51349ae7bc -R f7226b3a88877e57bdcf4f6eccd9d5fd +P 6824a78bc7b8582fc5c3a6ab05dd3ed996fc99b3 +R 531cb0ab110be0b71cbe712b6392904d U danielk1977 -Z 48f4477e2bf6d1e22b59c59df71537c6 +Z 7e47f34607634a7d8a9c0da4aab29935 diff --git a/manifest.uuid b/manifest.uuid index 71d5c058f5..2965911a72 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6824a78bc7b8582fc5c3a6ab05dd3ed996fc99b3 \ No newline at end of file +78f10ca0a6a02e9e8e6811489841a19e213f3afb \ No newline at end of file diff --git a/src/tclsqlite.c b/src/tclsqlite.c index f928faab7a..3f6d928035 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -11,7 +11,7 @@ ************************************************************************* ** A TCL Interface to SQLite ** -** $Id: tclsqlite.c,v 1.134 2005/11/26 00:25:03 drh Exp $ +** $Id: tclsqlite.c,v 1.135 2005/12/07 06:27:44 danielk1977 Exp $ */ #ifndef NO_TCL /* Omit this whole file if TCL is unavailable */ @@ -402,7 +402,7 @@ static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){ } default: { int bytes = sqlite3_value_bytes(pIn); - pVal = Tcl_NewStringObj(sqlite3_value_text(pIn), bytes); + pVal = Tcl_NewStringObj((char *)sqlite3_value_text(pIn), bytes); break; } } @@ -449,8 +449,8 @@ static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){ Tcl_GetWideIntFromObj(0, pVar, &v); sqlite3_result_int64(context, v); }else{ - data = Tcl_GetStringFromObj(pVar, &n); - sqlite3_result_text(context, data, n, SQLITE_TRANSIENT); + data = (unsigned char *)Tcl_GetStringFromObj(pVar, &n); + sqlite3_result_text(context, (char *)data, n, SQLITE_TRANSIENT); } } } @@ -1285,8 +1285,8 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ Tcl_GetWideIntFromObj(interp, pVar, &v); sqlite3_bind_int64(pStmt, i, v); }else{ - data = Tcl_GetStringFromObj(pVar, &n); - sqlite3_bind_text(pStmt, i, data, n, SQLITE_STATIC); + data = (unsigned char *)Tcl_GetStringFromObj(pVar, &n); + sqlite3_bind_text(pStmt, i, (char *)data, n, SQLITE_STATIC); Tcl_IncrRefCount(pVar); apParm[nParm++] = pVar; } @@ -1354,7 +1354,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ break; } default: { - pVal = dbTextToObj(sqlite3_column_text(pStmt, i)); + pVal = dbTextToObj((char *)sqlite3_column_text(pStmt, i)); break; } } diff --git a/src/vdbeapi.c b/src/vdbeapi.c index bc774b4f14..5d5e9cbb92 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -58,7 +58,7 @@ sqlite_int64 sqlite3_value_int64(sqlite3_value *pVal){ return sqlite3VdbeIntValue((Mem*)pVal); } const unsigned char *sqlite3_value_text(sqlite3_value *pVal){ - return (const char *)sqlite3ValueText(pVal, SQLITE_UTF8); + return (const unsigned char *)sqlite3ValueText(pVal, SQLITE_UTF8); } #ifndef SQLITE_OMIT_UTF16 const void *sqlite3_value_text16(sqlite3_value* pVal){ @@ -439,6 +439,7 @@ static const void *columnName( const void *(*xFunc)(Mem*), int useType ){ + const void *ret; Vdbe *p = (Vdbe *)pStmt; int n = sqlite3_column_count(pStmt); @@ -446,7 +447,13 @@ static const void *columnName( return 0; } N += useType*n; - return xFunc(&p->aColName[N]); + ret = xFunc(&p->aColName[N]); + + /* A malloc may have failed inside of the xFunc() call. If this is the case, + ** clear the mallocFailed flag and return NULL. + */ + sqlite3ClearMallocFailed(); + return ret; } diff --git a/src/vdbemem.c b/src/vdbemem.c index 8ee2e2bd24..31b0f3750a 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -41,11 +41,21 @@ int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){ #ifdef SQLITE_OMIT_UTF16 return SQLITE_ERROR; #else + + /* MemTranslate() may return SQLITE_OK or SQLITE_NOMEM. If NOMEM is returned, + ** then the encoding of the value may not have changed. + */ rc = sqlite3VdbeMemTranslate(pMem, desiredEnc); + assert(rc==SQLITE_OK || rc==SQLITE_NOMEM); + assert(rc==SQLITE_OK || pMem->enc!=desiredEnc); + assert(rc==SQLITE_NOMEM || pMem->enc==desiredEnc); + if( rc==SQLITE_NOMEM ){ +/* sqlite3VdbeMemRelease(pMem); pMem->flags = MEM_Null; pMem->z = 0; +*/ } return rc; #endif @@ -746,7 +756,8 @@ const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){ }else if( !(pVal->flags&MEM_Blob) ){ sqlite3VdbeMemStringify(pVal, enc); } - return (const void *)(pVal->z); + assert(pVal->enc==enc || sqlite3Tsd()->mallocFailed); + return (const void *)(pVal->enc==enc ? (pVal->z) : 0); } /* diff --git a/src/where.c b/src/where.c index d952d078fe..d643bde05f 100644 --- a/src/where.c +++ b/src/where.c @@ -16,7 +16,7 @@ ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". ** -** $Id: where.c,v 1.186 2005/12/06 12:53:01 danielk1977 Exp $ +** $Id: where.c,v 1.187 2005/12/07 06:27:44 danielk1977 Exp $ */ #include "sqliteInt.h" @@ -521,7 +521,7 @@ static int isLikeOrGlob( return 0; } sqlite3DequoteExpr(pRight); - z = pRight->token.z; + z = (char *)pRight->token.z; for(cnt=0; (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2]; cnt++){} if( cnt==0 || 255==(u8)z[cnt] ){ return 0; diff --git a/test/malloc3.test b/test/malloc3.test index 940fe9b0fc..f1259cda17 100644 --- a/test/malloc3.test +++ b/test/malloc3.test @@ -9,7 +9,11 @@ # #*********************************************************************** # -# $Id: malloc3.test,v 1.2 2005/12/06 17:48:32 danielk1977 Exp $ +# This file contains tests to ensure that the library handles malloc() failures +# correctly. The emphasis of these tests are the _prepare(), _step() and +# _finalize() calls. +# +# $Id: malloc3.test,v 1.3 2005/12/07 06:27:45 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -453,7 +457,7 @@ TEST 29 { } {a b c a b c 1 2 3 1 2 3} } -# Test a simple multi-file transaction +# Test a simple multi-file transaction # file delete -force test2.db SQL {ATTACH 'test2.db' AS aux;} diff --git a/test/malloc4.test b/test/malloc4.test new file mode 100644 index 0000000000..eee0afc68e --- /dev/null +++ b/test/malloc4.test @@ -0,0 +1,114 @@ +# 2005 November 30 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# +# This file contains tests to ensure that the library handles malloc() failures +# correctly. The emphasis in this file is on sqlite3_column_XXX() APIs. +# +# $Id: malloc4.test,v 1.1 2005/12/07 06:27:45 danielk1977 Exp $ + +#--------------------------------------------------------------------------- +# NOTES ON EXPECTED BEHAVIOUR +# +#--------------------------------------------------------------------------- + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +# Only run these tests if memory debugging is turned on. +if {[info command sqlite_malloc_stat]==""} { + puts "Skipping malloc tests: not compiled with -DSQLITE_MEMDEBUG..." + finish_test + return +} + + +proc do_stmt_test {id sql} { + set ::sql $sql + set go 1 + for {set n 1} {$go} {incr n} { + set testid "malloc4-$id.(iFail $n)" + + # Prepare the statement + do_test ${testid}.1 { + set ::STMT [sqlite3_prepare $::DB $sql -1 TAIL] + expr [string length $::STMT] > 0 + } {1} + + # Set the Nth malloc() to fail. + sqlite_malloc_fail $n + + # Test malloc failure in the _name(), _name16(), decltype() and + # decltype16() APIs. Calls that occur after the malloc() failure should + # return NULL. No error is raised though. + do_test ${testid}.2.1 { + set mf1 [expr [lindex [sqlite_malloc_stat] 2] <= 0] + set ::name8 [sqlite3_column_name $::STMT 0] + set mf2 [expr [lindex [sqlite_malloc_stat] 2] <= 0] + expr {$mf1 == $mf2 || $::name8 == ""} + } {1} + do_test ${testid}.2.2 { + set mf1 [expr [lindex [sqlite_malloc_stat] 2] <= 0] + set ::name16 [sqlite3_column_name16 $::STMT 0] + set ::name16 [encoding convertfrom unicode $::name16] + set ::name16 [string range $::name16 0 end-1] + set mf2 [expr [lindex [sqlite_malloc_stat] 2] <= 0] + expr {$mf1 == $mf2 || $::name16 == ""} + } {1} + do_test ${testid}.2.3 { + set mf1 [expr [lindex [sqlite_malloc_stat] 2] <= 0] + set ::name8_2 [sqlite3_column_name $::STMT 0] + set mf2 [expr [lindex [sqlite_malloc_stat] 2] <= 0] + expr {$mf1 == $mf2 || $::name8_2 == ""} + } {1} + set ::mallocFailed [expr [lindex [sqlite_malloc_stat] 2] <= 0] + do_test ${testid}.2.4 { + expr { + $::name8 == $::name8_2 && $::name16 == $::name8 && !$::mallocFailed || + $::name8 == $::name8_2 && $::name16 == "" && $::mallocFailed || + $::name8 == $::name16 && $::name8_2 == "" && $::mallocFailed || + $::name8_2 == $::name16 && $::name8 == "" && $::mallocFailed + } + } {1} + + if {$::mallocFailed == 0} { + sqlite_malloc_fail 0 + set go 0 + } + +if 0 { + # Test that if a malloc() failed the next call to sqlite3_step() returns + # SQLITE_ERROR. If malloc() did not fail, it should return SQLITE_ROW. + # + # Before running sqlite3_step(), make sure that malloc() is not about to + # fail. Memory allocation failures that occur within sqlite3_step() are + # tested elsewhere. + do_test ${testid}.3 { + set rc [sqlite3_step $::STMT] + list [expr $rc=="SQLITE_ERROR"] [expr $rc=="SQLITE_ROW"] + } [list $mallocFailed [expr !$mallocFailed]] +} + + do_test ${testid}.4 { + sqlite3_finalize $::STMT + } {SQLITE_OK} + } +} + +execsql { + CREATE TABLE tbl( + the_first_reasonably_long_column_name that_also_has_quite_a_lengthy_type + ); +} +do_stmt_test 1 "SELECT * FROM tbl" + +sqlite_malloc_fail 0 +finish_test + diff --git a/test/quick.test b/test/quick.test index 93db66bdbf..61bfcb09e7 100644 --- a/test/quick.test +++ b/test/quick.test @@ -1,7 +1,3 @@ -# 2001 September 15 -# -# The author disclaims copyright to this source code. In place of -# a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. @@ -10,7 +6,7 @@ #*********************************************************************** # This file runs all tests. # -# $Id: quick.test,v 1.36 2005/03/29 08:26:13 danielk1977 Exp $ +# $Id: quick.test,v 1.37 2005/12/07 06:27:45 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -29,6 +25,8 @@ set EXCLUDE { crash.test malloc.test malloc2.test + malloc3.test + malloc4.test memleak.test misuse.test quick.test