Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix a couple of fairly obscure cases where an assert() could fail following a malloc failure. (CVS 6360) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
cc0d925669ddeb55048e88aa5b4f658b |
User & Date: | danielk1977 2009-03-19 18:51:07.000 |
Context
2009-03-20
| ||
09:09 | Fix a problem in loadext.test causing an error on OSX. This is not a real problem, just a case of the test script expecting a slightly different error message than the one returned. (CVS 6361) (check-in: 18680989b5 user: danielk1977 tags: trunk) | |
2009-03-19
| ||
18:51 | Fix a couple of fairly obscure cases where an assert() could fail following a malloc failure. (CVS 6360) (check-in: cc0d925669 user: danielk1977 tags: trunk) | |
07:58 | Change sqlite3_step() to return SQLITE_LOCKED if a statement cannot be re-compiled due to locks on the shared-cache schema. Also add a blocking wrapper of sqlite3_prepare_v2() to the test code. (CVS 6359) (check-in: e8be1af922 user: danielk1977 tags: trunk) | |
Changes
Changes to src/legacy.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** ** $Id: legacy.c,v 1.32 2009/03/19 18:51:07 danielk1977 Exp $ */ #include "sqliteInt.h" /* ** Execute SQL code. Return one of the SQLITE_ success/failure ** codes. Also write an error message into memory obtained from |
︙ | ︙ | |||
97 98 99 100 101 102 103 | db->mallocFailed = 1; goto exec_out; } } } if( xCallback(pArg, nCol, azVals, azCols) ){ rc = SQLITE_ABORT; | | | | | 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | db->mallocFailed = 1; goto exec_out; } } } if( xCallback(pArg, nCol, azVals, azCols) ){ rc = SQLITE_ABORT; sqlite3VdbeFinalize((Vdbe *)pStmt); pStmt = 0; sqlite3Error(db, SQLITE_ABORT, 0); goto exec_out; } } if( rc!=SQLITE_ROW ){ rc = sqlite3VdbeFinalize((Vdbe *)pStmt); pStmt = 0; if( rc!=SQLITE_SCHEMA ){ nRetry = 0; zSql = zLeftover; while( sqlite3Isspace(zSql[0]) ) zSql++; } break; } } sqlite3DbFree(db, azCols); azCols = 0; } exec_out: if( pStmt ) sqlite3VdbeFinalize((Vdbe *)pStmt); sqlite3DbFree(db, azCols); rc = sqlite3ApiExit(db, rc); if( rc!=SQLITE_OK && rc==sqlite3_errcode(db) && pzErrMsg ){ int nErrMsg = 1 + sqlite3Strlen30(sqlite3_errmsg(db)); *pzErrMsg = sqlite3Malloc(nErrMsg); if( *pzErrMsg ){ |
︙ | ︙ |
Changes to src/main.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** ** $Id: main.c,v 1.533 2009/03/19 18:51:07 danielk1977 Exp $ */ #include "sqliteInt.h" #ifdef SQLITE_ENABLE_FTS3 # include "fts3.h" #endif #ifdef SQLITE_ENABLE_RTREE |
︙ | ︙ | |||
1241 1242 1243 1244 1245 1246 1247 1248 | const char *z; if( !db ){ return sqlite3ErrStr(SQLITE_NOMEM); } if( !sqlite3SafetyCheckSickOrOk(db) ){ return sqlite3ErrStr(SQLITE_MISUSE); } if( db->mallocFailed ){ | > | | < < | | | | > | 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 | const char *z; if( !db ){ return sqlite3ErrStr(SQLITE_NOMEM); } if( !sqlite3SafetyCheckSickOrOk(db) ){ return sqlite3ErrStr(SQLITE_MISUSE); } sqlite3_mutex_enter(db->mutex); if( db->mallocFailed ){ z = sqlite3ErrStr(SQLITE_NOMEM); }else{ z = (char*)sqlite3_value_text(db->pErr); assert( !db->mallocFailed ); if( z==0 ){ z = sqlite3ErrStr(db->errCode); } } sqlite3_mutex_leave(db->mutex); return z; } #ifndef SQLITE_OMIT_UTF16 /* |
︙ | ︙ | |||
1281 1282 1283 1284 1285 1286 1287 | if( !db ){ return (void *)outOfMem; } if( !sqlite3SafetyCheckSickOrOk(db) ){ return (void *)misuse; } sqlite3_mutex_enter(db->mutex); | | > > | | | | | | | | | | | | > | 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 | if( !db ){ return (void *)outOfMem; } if( !sqlite3SafetyCheckSickOrOk(db) ){ return (void *)misuse; } sqlite3_mutex_enter(db->mutex); if( db->mallocFailed ){ z = (void *)outOfMem; }else{ z = sqlite3_value_text16(db->pErr); if( z==0 ){ sqlite3ValueSetStr(db->pErr, -1, sqlite3ErrStr(db->errCode), SQLITE_UTF8, SQLITE_STATIC); z = sqlite3_value_text16(db->pErr); } /* A malloc() may have failed within the call to sqlite3_value_text16() ** above. If this is the case, then the db->mallocFailed flag needs to ** be cleared before returning. Do this directly, instead of via ** sqlite3ApiExit(), to avoid setting the database handle error message. */ db->mallocFailed = 0; } sqlite3_mutex_leave(db->mutex); return z; } #endif /* SQLITE_OMIT_UTF16 */ /* ** Return the most recent error code generated by an SQLite routine. If NULL is |
︙ | ︙ |
Changes to src/prepare.c.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the implementation of the sqlite3_prepare() ** interface, and routines that contribute to loading the database schema ** from disk. ** | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the implementation of the sqlite3_prepare() ** interface, and routines that contribute to loading the database schema ** from disk. ** ** $Id: prepare.c,v 1.111 2009/03/19 18:51:07 danielk1977 Exp $ */ #include "sqliteInt.h" /* ** Fill the InitData structure with an error message that indicates ** that the database is corrupt. */ |
︙ | ︙ | |||
644 645 646 647 648 649 650 | } assert( db->init.busy==0 || saveSqlFlag==0 ); if( db->init.busy==0 ){ Vdbe *pVdbe = sParse.pVdbe; sqlite3VdbeSetSql(pVdbe, zSql, (int)(sParse.zTail-zSql), saveSqlFlag); } | | | | 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 | } assert( db->init.busy==0 || saveSqlFlag==0 ); if( db->init.busy==0 ){ Vdbe *pVdbe = sParse.pVdbe; sqlite3VdbeSetSql(pVdbe, zSql, (int)(sParse.zTail-zSql), saveSqlFlag); } if( sParse.pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){ sqlite3VdbeFinalize(sParse.pVdbe); assert(!(*ppStmt)); }else{ *ppStmt = (sqlite3_stmt*)sParse.pVdbe; } if( zErrMsg ){ sqlite3Error(db, rc, "%s", zErrMsg); |
︙ | ︙ |
Changes to src/test_func.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Code for testing all sorts of SQLite interfaces. This code ** implements new SQL functions used by the test scripts. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Code for testing all sorts of SQLite interfaces. This code ** implements new SQL functions used by the test scripts. ** ** $Id: test_func.c,v 1.14 2009/03/19 18:51:07 danielk1977 Exp $ */ #include "sqlite3.h" #include "tcl.h" #include <stdlib.h> #include <string.h> #include <assert.h> |
︙ | ︙ | |||
141 142 143 144 145 146 147 148 149 150 151 152 153 154 | static void test_destructor_count( sqlite3_context *pCtx, int nArg, sqlite3_value **argv ){ sqlite3_result_int(pCtx, test_destructor_count_var); } /* ** Routines for testing the sqlite3_get_auxdata() and sqlite3_set_auxdata() ** interface. ** ** The test_auxdata() SQL function attempts to register each of its arguments ** as auxiliary data. If there are no prior registrations of aux data for | > > > > > > > > > > > > > > > > > > > | 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 | static void test_destructor_count( sqlite3_context *pCtx, int nArg, sqlite3_value **argv ){ sqlite3_result_int(pCtx, test_destructor_count_var); } /* ** The following aggregate function, test_agg_errmsg16(), takes zero ** arguments. It returns the text value returned by the sqlite3_errmsg16() ** API function. */ void sqlite3BeginBenignMalloc(void); void sqlite3EndBenignMalloc(void); static void test_agg_errmsg16_step(sqlite3_context *a, int b,sqlite3_value **c){ } static void test_agg_errmsg16_final(sqlite3_context *ctx){ const void *z; sqlite3 * db = sqlite3_context_db_handle(ctx); sqlite3_aggregate_context(ctx, 2048); sqlite3BeginBenignMalloc(); z = sqlite3_errmsg16(db); sqlite3EndBenignMalloc(); sqlite3_result_text16(ctx, z, -1, SQLITE_TRANSIENT); } /* ** Routines for testing the sqlite3_get_auxdata() and sqlite3_set_auxdata() ** interface. ** ** The test_auxdata() SQL function attempts to register each of its arguments ** as auxiliary data. If there are no prior registrations of aux data for |
︙ | ︙ | |||
314 315 316 317 318 319 320 321 322 323 324 325 326 327 | }; int i; for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){ sqlite3_create_function(db, aFuncs[i].zName, aFuncs[i].nArg, aFuncs[i].eTextRep, 0, aFuncs[i].xFunc, 0, 0); } return SQLITE_OK; } /* ** TCLCMD: autoinstall_test_functions ** ** Invoke this TCL command to use sqlite3_auto_extension() to cause | > > > > | 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 | }; int i; for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){ sqlite3_create_function(db, aFuncs[i].zName, aFuncs[i].nArg, aFuncs[i].eTextRep, 0, aFuncs[i].xFunc, 0, 0); } sqlite3_create_function(db, "test_agg_errmsg16", 0, SQLITE_ANY, 0, 0, test_agg_errmsg16_step, test_agg_errmsg16_final); return SQLITE_OK; } /* ** TCLCMD: autoinstall_test_functions ** ** Invoke this TCL command to use sqlite3_auto_extension() to cause |
︙ | ︙ |
Changes to src/vdbeapi.c.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This file contains code use to implement APIs that are part of the ** VDBE. ** | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This file contains code use to implement APIs that are part of the ** VDBE. ** ** $Id: vdbeapi.c,v 1.155 2009/03/19 18:51:07 danielk1977 Exp $ */ #include "sqliteInt.h" #include "vdbeInt.h" #if 0 && defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) /* ** The following structure contains pointers to the end points of a |
︙ | ︙ | |||
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 | */ int sqlite3_finalize(sqlite3_stmt *pStmt){ int rc; if( pStmt==0 ){ rc = SQLITE_OK; }else{ Vdbe *v = (Vdbe*)pStmt; #if SQLITE_THREADSAFE sqlite3_mutex *mutex = v->db->mutex; #endif sqlite3_mutex_enter(mutex); stmtLruRemove(v); rc = sqlite3VdbeFinalize(v); sqlite3_mutex_leave(mutex); } return rc; } /* ** Terminate the current execution of an SQL statement and reset it | > > | 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 | */ int sqlite3_finalize(sqlite3_stmt *pStmt){ int rc; if( pStmt==0 ){ rc = SQLITE_OK; }else{ Vdbe *v = (Vdbe*)pStmt; sqlite3 *db = v->db; #if SQLITE_THREADSAFE sqlite3_mutex *mutex = v->db->mutex; #endif sqlite3_mutex_enter(mutex); stmtLruRemove(v); rc = sqlite3VdbeFinalize(v); rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(mutex); } return rc; } /* ** Terminate the current execution of an SQL statement and reset it |
︙ | ︙ | |||
230 231 232 233 234 235 236 237 238 239 240 241 242 243 | }else{ Vdbe *v = (Vdbe*)pStmt; sqlite3_mutex_enter(v->db->mutex); rc = sqlite3VdbeReset(v); stmtLruAdd(v); sqlite3VdbeMakeReady(v, -1, 0, 0, 0); assert( (rc & (v->db->errMask))==rc ); sqlite3_mutex_leave(v->db->mutex); } return rc; } /* ** Set all the parameters in the compiled SQL statement to NULL. | > | 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 | }else{ Vdbe *v = (Vdbe*)pStmt; sqlite3_mutex_enter(v->db->mutex); rc = sqlite3VdbeReset(v); stmtLruAdd(v); sqlite3VdbeMakeReady(v, -1, 0, 0, 0); assert( (rc & (v->db->errMask))==rc ); rc = sqlite3ApiExit(v->db, rc); sqlite3_mutex_leave(v->db->mutex); } return rc; } /* ** Set all the parameters in the compiled SQL statement to NULL. |
︙ | ︙ |
Changes to src/vdbeblob.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This file contains code used to implement incremental BLOB I/O. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This file contains code used to implement incremental BLOB I/O. ** ** $Id: vdbeblob.c,v 1.30 2009/03/19 18:51:07 danielk1977 Exp $ */ #include "sqliteInt.h" #include "vdbeInt.h" #ifndef SQLITE_OMIT_INCRBLOB |
︙ | ︙ | |||
244 245 246 247 248 249 250 | }else if( rc==SQLITE_OK ){ sqlite3_snprintf(sizeof(zErr), zErr, "no such rowid: %lld", iRow); rc = SQLITE_ERROR; } blob_open_out: zErr[sizeof(zErr)-1] = '\0'; | | | | 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 | }else if( rc==SQLITE_OK ){ sqlite3_snprintf(sizeof(zErr), zErr, "no such rowid: %lld", iRow); rc = SQLITE_ERROR; } blob_open_out: zErr[sizeof(zErr)-1] = '\0'; if( v && (rc!=SQLITE_OK || db->mallocFailed) ){ sqlite3VdbeFinalize(v); } sqlite3Error(db, rc, (rc==SQLITE_OK?0:zErr)); rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); return rc; } |
︙ | ︙ |
Changes to src/vtab.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2006 June 10 ** ** 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 code used to help implement virtual tables. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2006 June 10 ** ** 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 code used to help implement virtual tables. ** ** $Id: vtab.c,v 1.83 2009/03/19 18:51:07 danielk1977 Exp $ */ #ifndef SQLITE_OMIT_VIRTUALTABLE #include "sqliteInt.h" static int createModule( sqlite3 *db, /* Database in which module is registered */ const char *zName, /* Name assigned to this module */ |
︙ | ︙ | |||
567 568 569 570 571 572 573 | } else { sqlite3Error(db, SQLITE_ERROR, zErr); sqlite3DbFree(db, zErr); rc = SQLITE_ERROR; } sParse.declareVtab = 0; | | > > | 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 | } else { sqlite3Error(db, SQLITE_ERROR, zErr); sqlite3DbFree(db, zErr); rc = SQLITE_ERROR; } sParse.declareVtab = 0; if( sParse.pVdbe ){ sqlite3VdbeFinalize(sParse.pVdbe); } sqlite3DeleteTable(sParse.pNewTable); sParse.pNewTable = 0; assert( (rc&0xff)==rc ); rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); return rc; |
︙ | ︙ |
Changes to test/malloc.test.
︙ | ︙ | |||
12 13 14 15 16 17 18 | # This file attempts to check the behavior of the SQLite library in # an out-of-memory situation. When compiled with -DSQLITE_DEBUG=1, # the SQLite library accepts a special command (sqlite3_memdebug_fail N C) # which causes the N-th malloc to fail. This 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. # | | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | # This file attempts to check the behavior of the SQLite library in # an out-of-memory situation. When compiled with -DSQLITE_DEBUG=1, # the SQLite library accepts a special command (sqlite3_memdebug_fail N C) # which causes the N-th malloc to fail. This 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.77 2009/03/19 18:51:07 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Only run these tests if memory debugging is turned on. # |
︙ | ︙ | |||
812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 | for {set i 0} {$i<500} {incr i} { db eval {INSERT INTO abc VALUES(randstr(100,100), randstr(1000,1000))} } } } -sqlbody { SELECT count(*) FROM abc; } # Ensure that no file descriptors were leaked. do_test malloc-99.X { catch {db close} set sqlite_open_file_count } {0} puts open-file-count=$sqlite_open_file_count finish_test | > > > > > > > > > > > > > > > > > > > > > > | 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 | for {set i 0} {$i<500} {incr i} { db eval {INSERT INTO abc VALUES(randstr(100,100), randstr(1000,1000))} } } } -sqlbody { SELECT count(*) FROM abc; } proc f {args} { error "Quite a long error!" } do_malloc_test 35 -tclprep { db func f f set ::STMT [sqlite3_prepare db "SELECT f()" -1 DUMMY] sqlite3_step $::STMT } -tclbody { sqlite3_finalize $::STMT } -cleanup { # At one point an assert( !db->mallocFailed ) could fail in the following # call to sqlite3_errmsg(). Because sqlite3_finalize() had failed to clear # the flag before returning. sqlite3_errmsg16 db } do_malloc_test 36 -sqlprep { CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2); INSERT INTO t1 VALUES(3, 4); } -sqlbody { SELECT test_agg_errmsg16(), group_concat(a) FROM t1 } # Ensure that no file descriptors were leaked. do_test malloc-99.X { catch {db close} set sqlite_open_file_count } {0} puts open-file-count=$sqlite_open_file_count finish_test |