Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Many small changes to ensure memory is not leaked after malloc() fails. (CVS 2808) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
601c335463aaabc2e9918e4b9298cff6 |
User & Date: | danielk1977 2005-12-09 14:25:08.000 |
Context
2005-12-09
| ||
14:39 | Define the sqliteMalloc() macro differently to avoid a compiler warning. (CVS 2809) (check-in: 3d177bde71 user: danielk1977 tags: trunk) | |
14:25 | Many small changes to ensure memory is not leaked after malloc() fails. (CVS 2808) (check-in: 601c335463 user: danielk1977 tags: trunk) | |
02:35 | Add more stress testing to autovacuum in an (unsuccessful) attempt to reproduce a reported problem. Even though these tests did not uncover anything amiss, extra tests never hurt... (CVS 2807) (check-in: d8a8933ff3 user: drh tags: trunk) | |
Changes
Changes to src/attach.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2003 April 6 ** ** 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 implement the ATTACH and DETACH commands. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2003 April 6 ** ** 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 implement the ATTACH and DETACH commands. ** ** $Id: attach.c,v 1.37 2005/12/09 14:25:08 danielk1977 Exp $ */ #include "sqliteInt.h" /* ** Resolve an expression that was part of an ATTACH or DETACH statement. This ** is slightly different from resolving a normal SQL expression, because simple ** identifiers are treated as strings, not possible column names or aliases. |
︙ | ︙ | |||
257 258 259 260 261 262 263 | int rc; NameContext sName; Vdbe *v; FuncDef *pFunc; sqlite3* db = pParse->db; #ifndef SQLITE_OMIT_AUTHORIZATION | > > | | | | | > > | > | 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 | int rc; NameContext sName; Vdbe *v; FuncDef *pFunc; sqlite3* db = pParse->db; #ifndef SQLITE_OMIT_AUTHORIZATION assert( sqlite3Tsd()->mallocFailed || pAuthArg ); if( pAuthArg ){ char *zAuthArg = sqlite3NameFromToken(&pAuthArg->span); if( !zAuthArg ){ goto attach_end; } rc = sqlite3AuthCheck(pParse, type, zAuthArg, 0, 0); sqliteFree(zAuthArg); if(rc!=SQLITE_OK ){ goto attach_end; } } #endif /* SQLITE_OMIT_AUTHORIZATION */ memset(&sName, 0, sizeof(NameContext)); sName.pParse = pParse; if( |
︙ | ︙ | |||
300 301 302 303 304 305 306 | sqlite3VdbeAddOp(v, OP_Expire, (type==SQLITE_ATTACH), 0); } attach_end: sqlite3ExprDelete(pFilename); sqlite3ExprDelete(pDbname); sqlite3ExprDelete(pKey); | < | 305 306 307 308 309 310 311 312 313 314 315 316 317 318 | sqlite3VdbeAddOp(v, OP_Expire, (type==SQLITE_ATTACH), 0); } attach_end: sqlite3ExprDelete(pFilename); sqlite3ExprDelete(pDbname); sqlite3ExprDelete(pKey); } /* ** Called by the parser to compile a DETACH statement. ** ** DETACH pDbname */ |
︙ | ︙ |
Changes to src/os_unix.c.
︙ | ︙ | |||
629 630 631 632 633 634 635 636 637 638 639 640 641 642 | ** On success, write the file handle into *id and return SQLITE_OK. ** ** On failure, return SQLITE_CANTOPEN. */ static int unixOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){ int rc; unixFile f; assert( 0==*pId ); if( access(zFilename, 0)==0 ){ return SQLITE_CANTOPEN; } SET_THREADID(&f); f.dirfd = -1; | > | 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 | ** On success, write the file handle into *id and return SQLITE_OK. ** ** On failure, return SQLITE_CANTOPEN. */ static int unixOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){ int rc; unixFile f; int fd; assert( 0==*pId ); if( access(zFilename, 0)==0 ){ return SQLITE_CANTOPEN; } SET_THREADID(&f); f.dirfd = -1; |
︙ | ︙ | |||
1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 | ** OsFile. If we run out of memory, close the file and return NULL. */ static int allocateUnixFile(unixFile *pInit, OsFile **pId){ unixFile *pNew; pNew = sqliteMalloc( sizeof(unixFile) ); if( pNew==0 ){ close(pInit->h); *pId = 0; return SQLITE_NOMEM; }else{ *pNew = *pInit; pNew->pMethod = &sqlite3UnixIoMethod; *pId = (OsFile*)pNew; OpenCounter(+1); | > > | 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 | ** OsFile. If we run out of memory, close the file and return NULL. */ static int allocateUnixFile(unixFile *pInit, OsFile **pId){ unixFile *pNew; pNew = sqliteMalloc( sizeof(unixFile) ); if( pNew==0 ){ close(pInit->h); releaseLockInfo(pInit->pLock); releaseOpenCnt(pInit->pOpen); *pId = 0; return SQLITE_NOMEM; }else{ *pNew = *pInit; pNew->pMethod = &sqlite3UnixIoMethod; *pId = (OsFile*)pNew; OpenCounter(+1); |
︙ | ︙ |
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.6 2005/12/09 14:25:08 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> /* ** Fill the InitData structure with an error message that indicates |
︙ | ︙ | |||
499 500 501 502 503 504 505 | ** inside of the sqlite3Error() call above or something. */ if( sqlite3Tsd()->mallocFailed ){ rc = SQLITE_NOMEM; sqlite3Error(db, rc, 0); } | | | 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 | ** inside of the sqlite3Error() call above or something. */ if( sqlite3Tsd()->mallocFailed ){ rc = SQLITE_NOMEM; sqlite3Error(db, rc, 0); } sqlite3MallocClearFailed(); return rc; } #ifndef SQLITE_OMIT_UTF16 /* ** Compile the UTF-16 encoded SQL statement zSql into a statement handle. */ |
︙ | ︙ |
Changes to src/shell.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 to implement the "sqlite" command line ** utility for accessing SQLite databases. ** | | | 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 to implement the "sqlite" command line ** utility for accessing SQLite databases. ** ** $Id: shell.c,v 1.129 2005/12/09 14:25:08 danielk1977 Exp $ */ #include <stdlib.h> #include <string.h> #include <stdio.h> #include <assert.h> #include "sqlite3.h" #include <ctype.h> |
︙ | ︙ | |||
77 78 79 80 81 82 83 | static char mainPrompt[20]; /* First line prompt. default: "sqlite> "*/ static char continuePrompt[20]; /* Continuation prompt. default: " ...> " */ /* ** Determines if a string is a number of not. */ | | | 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | static char mainPrompt[20]; /* First line prompt. default: "sqlite> "*/ static char continuePrompt[20]; /* Continuation prompt. default: " ...> " */ /* ** Determines if a string is a number of not. */ static int isNumber(const char *z, int *realnum){ if( *z=='-' || *z=='+' ) z++; if( !isdigit(*z) ){ return 0; } z++; if( realnum ) *realnum = 0; while( isdigit(*z) ){ z++; } |
︙ | ︙ | |||
686 687 688 689 690 691 692 693 | zTmp = appendText(zTmp, zTable, '"'); if( zTmp ){ zSelect = appendText(zSelect, zTmp, '\''); } zSelect = appendText(zSelect, " || ' VALUES(' || ", 0); rc = sqlite3_step(pTableInfo); while( rc==SQLITE_ROW ){ zSelect = appendText(zSelect, "quote(", 0); | > | | 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 | zTmp = appendText(zTmp, zTable, '"'); if( zTmp ){ zSelect = appendText(zSelect, zTmp, '\''); } zSelect = appendText(zSelect, " || ' VALUES(' || ", 0); rc = sqlite3_step(pTableInfo); while( rc==SQLITE_ROW ){ const char *zText = (const char *)sqlite3_column_text(pTableInfo, 1); zSelect = appendText(zSelect, "quote(", 0); zSelect = appendText(zSelect, zText, '"'); rc = sqlite3_step(pTableInfo); if( rc==SQLITE_ROW ){ zSelect = appendText(zSelect, ") || ', ' || ", 0); }else{ zSelect = appendText(zSelect, ") ", 0); } } |
︙ | ︙ |
Changes to src/sqliteInt.h.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 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. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 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. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.431 2005/12/09 14:25:08 danielk1977 Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ /* ** Many people are failing to set -DNDEBUG=1 when compiling SQLite. ** Setting NDEBUG makes the code smaller and run faster. So the following |
︙ | ︙ | |||
229 230 231 232 233 234 235 | /* ** This macro casts a pointer to an integer. Useful for doing ** pointer arithmetic. */ #define Addr(X) ((uptr)X) | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 | /* ** This macro casts a pointer to an integer. Useful for doing ** pointer arithmetic. */ #define Addr(X) ((uptr)X) #ifdef SQLITE_MEMDEBUG /* ** The following global variables are used for testing and debugging ** only. They only work if SQLITE_DEBUG is defined. */ extern int sqlite3_nMalloc; /* Number of sqliteMalloc() calls */ extern int sqlite3_nFree; /* Number of sqliteFree() calls */ extern int sqlite3_iMallocFail; /* Fail sqliteMalloc() after this many calls */ extern int sqlite3_iMallocReset; /* Set iMallocFail to this when it reaches 0 */ #define ENTER_MALLOC (\ sqlite3Tsd()->zFile = __FILE__, sqlite3Tsd()->iLine = __LINE__ \ ) #else #define ENTER_MALLOC 0 #endif #define sqliteFree(x) sqlite3FreeX(x) #define sqliteMalloc(x) (ENTER_MALLOC, sqlite3Malloc(x)) #define sqliteMallocRaw(x) (ENTER_MALLOC, sqlite3MallocRaw(x)) #define sqliteRealloc(x,y) (ENTER_MALLOC, sqlite3Realloc(x,y)) #define sqliteStrDup(x) (ENTER_MALLOC, sqlite3StrDup(x)) #define sqliteStrNDup(x,y) (ENTER_MALLOC, sqlite3StrNDup(x,y)) /* ** An instance of this structure is allocated for each thread that uses SQLite. */ typedef struct SqliteTsd SqliteTsd; struct SqliteTsd { int mallocFailed; /* True after a malloc() has failed */ #ifndef NDEBUG int mallocAllowed; /* assert() in sqlite3Malloc() if not set */ #endif #ifdef SQLITE_MEMDEBUG int isFail; /* True if all malloc() calls should fail */ const char *zFile; /* Filename to associate debugging info with */ int iLine; /* Line number to associate debugging info with */ void *pFirst; /* Pointer to linked list of allocations */ #endif }; /* ** Name of the master database table. The master database table ** is a special table that holds the names and attributes of all ** user tables and indices. */ #define MASTER_NAME "sqlite_master" |
︙ | ︙ | |||
1375 1376 1377 1378 1379 1380 1381 | ** from sqlite3Init and OP_ParseSchema into the sqlite3InitCallback. */ typedef struct { sqlite3 *db; /* The database being initialized */ char **pzErrMsg; /* Error message stored here */ } InitData; | < < < < < < < < | 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 | ** from sqlite3Init and OP_ParseSchema into the sqlite3InitCallback. */ typedef struct { sqlite3 *db; /* The database being initialized */ char **pzErrMsg; /* Error message stored here */ } InitData; /* * This global flag is set for performance testing of triggers. When it is set * SQLite will perform the overhead of building new and old trigger references * even when no triggers exist */ extern int sqlite3_always_code_trigger_setup; |
︙ | ︙ | |||
1413 1414 1415 1416 1417 1418 1419 | int sqlite3StrICmp(const char *, const char *); int sqlite3StrNICmp(const char *, const char *, int); int sqlite3HashNoCase(const char *, int); int sqlite3IsNumber(const char*, int*, u8); int sqlite3Compare(const char *, const char *); int sqlite3SortCompare(const char *, const char *); void sqlite3RealToSortable(double r, char *); | | < < < < < < < | | | | | | < < > | 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 | int sqlite3StrICmp(const char *, const char *); int sqlite3StrNICmp(const char *, const char *, int); int sqlite3HashNoCase(const char *, int); int sqlite3IsNumber(const char*, int*, u8); int sqlite3Compare(const char *, const char *); int sqlite3SortCompare(const char *, const char *); void sqlite3RealToSortable(double r, char *); void *sqlite3Malloc(int); void *sqlite3MallocRaw(int); void sqlite3Free(void*); void *sqlite3Realloc(void*,int); char *sqlite3StrDup(const char*); char *sqlite3StrNDup(const char*, int); # define sqlite3CheckMemory(a,b) void sqlite3ReallocOrFree(void**,int); void sqlite3FreeX(void*); void *sqlite3MallocX(int); char *sqlite3MPrintf(const char*, ...); char *sqlite3VMPrintf(const char*, va_list); void sqlite3DebugPrintf(const char*, ...); void *sqlite3TextToPtr(const char*); void sqlite3SetString(char **, ...); void sqlite3ErrorMsg(Parse*, const char*, ...); void sqlite3Dequote(char*); |
︙ | ︙ | |||
1673 1674 1675 1676 1677 1678 1679 | int sqlite3InvokeBusyHandler(BusyHandler*); int sqlite3FindDb(sqlite3*, Token*); void sqlite3AnalysisLoad(sqlite3*,int iDB); void sqlite3DefaultRowEst(Index*); void sqlite3RegisterLikeFunctions(sqlite3*, int); int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*); SqliteTsd *sqlite3Tsd(); | < > > > > > > > > > | 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 | int sqlite3InvokeBusyHandler(BusyHandler*); int sqlite3FindDb(sqlite3*, Token*); void sqlite3AnalysisLoad(sqlite3*,int iDB); void sqlite3DefaultRowEst(Index*); void sqlite3RegisterLikeFunctions(sqlite3*, int); int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*); SqliteTsd *sqlite3Tsd(); void sqlite3AttachFunctions(sqlite3 *); void sqlite3MallocClearFailed(); #ifdef NDEBUG #define sqlite3MallocDisallow() #define sqlite3MallocAllow() #else void sqlite3MallocDisallow(); void sqlite3MallocAllow(); #endif #ifdef SQLITE_SSE #include "sseInt.h" #endif #endif |
Changes to src/test1.c.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** Code for testing the printf() interface to SQLite. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** | | | 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. ** ************************************************************************* ** Code for testing the printf() interface to SQLite. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** ** $Id: test1.c,v 1.172 2005/12/09 14:25:08 danielk1977 Exp $ */ #include "sqliteInt.h" #include "tcl.h" #include "os.h" #include <stdlib.h> #include <string.h> |
︙ | ︙ | |||
828 829 830 831 832 833 834 835 836 837 838 839 840 841 | char **argv /* Text of each argument */ ){ char zBuf[200]; sprintf(zBuf, "%d %d %d", sqlite3_nMalloc, sqlite3_nFree, sqlite3_iMallocFail); Tcl_AppendResult(interp, zBuf, 0); return TCL_OK; } #endif /* ** Usage: sqlite_abort ** ** Shutdown the process immediately. This is not a clean shutdown. ** This command is used to test the recoverability of a database in | > > > > > > > > > | 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 | char **argv /* Text of each argument */ ){ char zBuf[200]; sprintf(zBuf, "%d %d %d", sqlite3_nMalloc, sqlite3_nFree, sqlite3_iMallocFail); Tcl_AppendResult(interp, zBuf, 0); return TCL_OK; } static int sqlite_malloc_outstanding( void *NotUsed, Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ char **argv /* Text of each argument */ ){ extern int sqlite3OutstandingMallocs(Tcl_Interp *interp); return sqlite3OutstandingMallocs(interp); } #endif /* ** Usage: sqlite_abort ** ** Shutdown the process immediately. This is not a clean shutdown. ** This command is used to test the recoverability of a database in |
︙ | ︙ | |||
3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 | { "sqlite3_create_function", (Tcl_CmdProc*)test_create_function }, { "sqlite3_create_aggregate", (Tcl_CmdProc*)test_create_aggregate }, { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func }, { "sqlite_abort", (Tcl_CmdProc*)sqlite_abort }, #ifdef SQLITE_MEMDEBUG { "sqlite_malloc_fail", (Tcl_CmdProc*)sqlite_malloc_fail }, { "sqlite_malloc_stat", (Tcl_CmdProc*)sqlite_malloc_stat }, #endif { "sqlite_bind", (Tcl_CmdProc*)test_bind }, { "breakpoint", (Tcl_CmdProc*)test_breakpoint }, { "sqlite3_key", (Tcl_CmdProc*)test_key }, { "sqlite3_rekey", (Tcl_CmdProc*)test_rekey }, { "sqlite_set_magic", (Tcl_CmdProc*)sqlite_set_magic }, { "sqlite3_interrupt", (Tcl_CmdProc*)test_interrupt }, | > | 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 | { "sqlite3_create_function", (Tcl_CmdProc*)test_create_function }, { "sqlite3_create_aggregate", (Tcl_CmdProc*)test_create_aggregate }, { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func }, { "sqlite_abort", (Tcl_CmdProc*)sqlite_abort }, #ifdef SQLITE_MEMDEBUG { "sqlite_malloc_fail", (Tcl_CmdProc*)sqlite_malloc_fail }, { "sqlite_malloc_stat", (Tcl_CmdProc*)sqlite_malloc_stat }, { "sqlite_malloc_outstanding", (Tcl_CmdProc*)sqlite_malloc_outstanding}, #endif { "sqlite_bind", (Tcl_CmdProc*)test_bind }, { "breakpoint", (Tcl_CmdProc*)test_breakpoint }, { "sqlite3_key", (Tcl_CmdProc*)test_key }, { "sqlite3_rekey", (Tcl_CmdProc*)test_rekey }, { "sqlite_set_magic", (Tcl_CmdProc*)sqlite_set_magic }, { "sqlite3_interrupt", (Tcl_CmdProc*)test_interrupt }, |
︙ | ︙ | |||
3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 | static int bitmask_size = sizeof(Bitmask)*8; int i; extern int sqlite3_os_trace; extern int sqlite3_where_trace; extern int sqlite3_sync_count, sqlite3_fullsync_count; extern int sqlite3_opentemp_count; extern int sqlite3_memUsed; extern int sqlite3_memMax; extern int sqlite3_like_count; #if OS_WIN extern int sqlite3_os_type; #endif #ifdef SQLITE_DEBUG extern int sqlite3_vdbe_addop_trace; | > | 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 | static int bitmask_size = sizeof(Bitmask)*8; int i; extern int sqlite3_os_trace; extern int sqlite3_where_trace; extern int sqlite3_sync_count, sqlite3_fullsync_count; extern int sqlite3_opentemp_count; extern int sqlite3_memUsed; extern int sqlite3_malloc_id; extern int sqlite3_memMax; extern int sqlite3_like_count; #if OS_WIN extern int sqlite3_os_type; #endif #ifdef SQLITE_DEBUG extern int sqlite3_vdbe_addop_trace; |
︙ | ︙ | |||
3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 | (char*)&sqlite3_interrupt_count, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_open_file_count", (char*)&sqlite3_open_file_count, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_current_time", (char*)&sqlite3_current_time, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_os_trace", (char*)&sqlite3_os_trace, TCL_LINK_INT); #if OS_WIN Tcl_LinkVar(interp, "sqlite_os_type", (char*)&sqlite3_os_type, TCL_LINK_INT); #endif #ifdef SQLITE_TEST Tcl_LinkVar(interp, "sqlite_query_plan", (char*)&query_plan, TCL_LINK_STRING|TCL_LINK_READ_ONLY); | > > | 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 | (char*)&sqlite3_interrupt_count, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_open_file_count", (char*)&sqlite3_open_file_count, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_current_time", (char*)&sqlite3_current_time, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_os_trace", (char*)&sqlite3_os_trace, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_malloc_id", (char*)&sqlite3_malloc_id, TCL_LINK_STRING); #if OS_WIN Tcl_LinkVar(interp, "sqlite_os_type", (char*)&sqlite3_os_type, TCL_LINK_INT); #endif #ifdef SQLITE_TEST Tcl_LinkVar(interp, "sqlite_query_plan", (char*)&query_plan, TCL_LINK_STRING|TCL_LINK_READ_ONLY); |
︙ | ︙ |
Changes to src/trigger.c.
︙ | ︙ | |||
195 196 197 198 199 200 201 | ){ Trigger *pTrig = 0; /* The trigger whose construction is finishing up */ sqlite3 *db = pParse->db; /* The database */ DbFixer sFix; pTrig = pParse->pNewTrigger; pParse->pNewTrigger = 0; | | | 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | ){ Trigger *pTrig = 0; /* The trigger whose construction is finishing up */ sqlite3 *db = pParse->db; /* The database */ DbFixer sFix; pTrig = pParse->pNewTrigger; pParse->pNewTrigger = 0; if( pParse->nErr || !pTrig ) goto triggerfinish_cleanup; pTrig->step_list = pStepList; while( pStepList ){ pStepList->pTrig = pTrig; pStepList = pStepList->pNext; } if( sqlite3FixInit(&sFix, pParse, pTrig->iDb, "trigger", &pTrig->nameToken) && sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){ |
︙ | ︙ | |||
308 309 310 311 312 313 314 | ** a trigger step. Return a pointer to a TriggerStep structure. ** ** The parser calls this routine when it finds a SELECT statement in ** body of a TRIGGER. */ TriggerStep *sqlite3TriggerSelectStep(Select *pSelect){ TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep)); | | > > > | 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 | ** a trigger step. Return a pointer to a TriggerStep structure. ** ** The parser calls this routine when it finds a SELECT statement in ** body of a TRIGGER. */ TriggerStep *sqlite3TriggerSelectStep(Select *pSelect){ TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep)); if( pTriggerStep==0 ) { sqlite3SelectDelete(pSelect); return 0; } pTriggerStep->op = TK_SELECT; pTriggerStep->pSelect = pSelect; pTriggerStep->orconf = OE_Default; sqlitePersistTriggerStep(pTriggerStep); return pTriggerStep; |
︙ | ︙ |
Changes to src/util.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** | | < > | < | > | < | > | | | < < < < | > > > > | > > > > > > > > > > > > > > > > > > > > > > > > < | | > > > > > > | > > > | > | > > > > > > > > > > > > > > > > > > > < < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | < < < < < < < < < < | > > > > < < < < < > | | > < | > | > > | > > > > | | < < < < | < < | > | > > | | > | > > > > > > > > | > | > | | | | | | | < | > | | | | | | < < | < < > | > > > > > > | | > > > | > > > | | > > | | < | | > > > > > > > > > > | > > > | > | > | < < | > > > > | > | > | > | < > | > | | | > > | > | > > | < | < > | < > > | < < > | > | < > > > | < < < > > | > | < < < | > | | | | | < > > > > > > > > > | > > | > > > | > > | > > > > > > > > > > > > > > > > > > > > | < > | | > | > > > < < | | < < | < > | | < > > > > > > | | < < < < | > > > | > > > > > | > > | | | < < < > | < | < < < < < < < < < | < | > | | | < > > > > > > > > > > > > > > > > > > > > > > | | < < | | | | | < < < | | > | > > > > | | | | > | > > | < < | > > | < > < > > | > < | > > > > | | | < < < | < < < < < | | < | | | < | < < < < | < < < < < < < < < < < < < < < < < < < < | < | | | < < < < < < < < < < < < < < | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 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 136 137 138 139 140 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 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 | ** ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** ** $Id: util.c,v 1.150 2005/12/09 14:25:09 danielk1977 Exp $ */ #include "sqliteInt.h" #include <stdarg.h> #include <ctype.h> /* ** MALLOC WRAPPER ARCHITECTURE ** ** The sqlite code accesses dynamic memory allocation/deallocation by invoking ** the following four APIs (which may be implemented as macros). ** ** sqlite3Malloc() ** sqlite3MallocRaw() ** sqlite3Realloc() ** sqlite3ReallocOrFree() ** sqlite3Free() ** ** The function sqlite3FreeX performs the same task as sqlite3Free and is ** guaranteed to be a real function. ** ** The above APIs are implemented in terms of the functions provided at the Os ** level (not in this file). The Os level interface is never accessed directly ** by code outside of this file. ** ** sqlite3OsMalloc() ** sqlite3OsRealloc() ** sqlite3OsFree() ** sqlite3OsAllocationSize() ** ** Functions sqlite3MallocRaw() and sqlite3Realloc() may invoke ** sqlite3_release_memory() if a call to sqlite3OsMalloc() or ** sqlite3OsRealloc() fails. Function sqlite3Malloc() usually invokes ** sqlite3MallocRaw(). ** ** MALLOC TEST WRAPPER ARCHITECTURE ** ** The test wrapper provides extra test facilities to ensure the library ** does not leak memory and handles the failure of the underlying (Os level) ** allocation system correctly. It is only present if the library is ** compiled with the SQLITE_MEMDEBUG macro set. ** ** * Guardposts to detect overwrites. ** * Ability to cause a specific Malloc() or Realloc() to fail. ** * Audit outstanding memory allocations (i.e check for leaks). */ /* ** sqlite3OsMalloc ** sqlite3OsRealloc ** sqlite3OsOsFree ** sqlite3OsAllocationSize ** ** Implementation of the os level dynamic memory allocation interface in terms ** of the standard malloc(), realloc() and free() found in many operating ** systems. No rocket science here. */ void *sqlite3OsMalloc(int n){ char *p = (char *)malloc(n+8); assert(n>0); assert(sizeof(int)<=8); if( p ){ *(int *)p = n; } return (void *)(p + 8); } void *sqlite3OsRealloc(void *p, int n){ char *p2 = ((char *)p - 8); assert(n>0); p2 = realloc(p2, n+8); if( p2 ){ *(int *)p2 = n; } return (void *)((char *)p2 + 8); } void sqlite3OsFree(void *p){ assert(p); free((void *)((char *)p - 8)); } int sqlite3OsAllocationSize(void *p){ return *(int *)((char *)p - 8); } /* ** TODO! */ #define sqlite3_release_memory(x) 0 #ifdef SQLITE_MEMDEBUG /*-------------------------------------------------------------------------- ** Begin code for memory allocation system test layer. ** ** Memory debugging is turned on by defining the SQLITE_MEMDEBUG macro. */ /* Figure out whether or not to store backtrace() information for each malloc. ** The backtrace() function is only used if SQLITE_MEMDEBUG is set to 2 or ** greater and glibc is in use. If we don't want to use backtrace(), then just ** define it as an empty macro and set the amount of space reserved to 0. */ #if defined(__GLIBC__) && SQLITE_MEMDEBUG>1 extern int backtrace(void **, int); #define TESTALLOC_STACKSIZE 128 #define TESTALLOC_STACKFRAMES ((TESTALLOC_STACKSIZE-8)/sizeof(void*)) #else #define backtrace(x, y) 0 #define TESTALLOC_STACKSIZE 0 #define TESTALLOC_STACKFRAMES 0 #endif /* ** Number of 32-bit guard words. This should probably be a multiple of ** 2 since on 64-bit machines we want the value returned by sqliteMalloc() ** to be 8-byte aligned. */ #define TESTALLOC_NGUARD 2 /* ** Size reserved for storing file-name along with each malloc()ed blob. */ #define TESTALLOC_FILESIZE 64 /* ** Size reserved for storing the user string. */ #define TESTALLOC_USERSIZE 64 const char *sqlite3_malloc_id = 0; /* ** Blocks used by the test layer have the following format: ** ** <sizeof(void *) pNext pointer> ** <sizeof(void *) pPrev pointer> ** <TESTALLOC_NGUARD 32-bit guard words> ** <The application level allocation> ** <TESTALLOC_NGUARD 32-bit guard words> ** <32-bit line number> ** <TESTALLOC_FILESIZE bytes containing null-terminated file name> ** <TESTALLOC_STACKSIZE bytes of backtrace() output> */ #define TESTALLOC_OFFSET_GUARD1(p) (sizeof(void *) * 2) #define TESTALLOC_OFFSET_DATA(p) ( \ TESTALLOC_OFFSET_GUARD1(p) + sizeof(u32) * TESTALLOC_NGUARD \ ) #define TESTALLOC_OFFSET_GUARD2(p) ( \ TESTALLOC_OFFSET_DATA(p) + sqlite3OsAllocationSize(p) - TESTALLOC_OVERHEAD \ ) #define TESTALLOC_OFFSET_LINENUMBER(p) ( \ TESTALLOC_OFFSET_GUARD2(p) + sizeof(u32) * TESTALLOC_NGUARD \ ) #define TESTALLOC_OFFSET_FILENAME(p) ( \ TESTALLOC_OFFSET_LINENUMBER(p) + sizeof(u32) \ ) #define TESTALLOC_OFFSET_USER(p) ( \ TESTALLOC_OFFSET_FILENAME(p) + TESTALLOC_FILESIZE \ ) #define TESTALLOC_OFFSET_STACK(p) ( \ TESTALLOC_OFFSET_USER(p) + TESTALLOC_USERSIZE + 8 - \ (TESTALLOC_OFFSET_USER(p) % 8) \ ) #define TESTALLOC_OVERHEAD ( \ sizeof(void *)*2 + /* pPrev and pNext pointers */ \ TESTALLOC_NGUARD*sizeof(u32)*2 + /* Guard words */ \ sizeof(u32) + TESTALLOC_FILESIZE + /* File and line number */ \ TESTALLOC_USERSIZE + /* User string */ \ TESTALLOC_STACKSIZE /* backtrace() stack */ \ ) /* ** For keeping track of the number of mallocs and frees. This ** is used to check for memory leaks. The iMallocFail and iMallocReset ** values are used to simulate malloc() failures during testing in ** order to verify that the library correctly handles an out-of-memory ** condition. */ int sqlite3_nMalloc; /* Number of sqliteMalloc() calls */ int sqlite3_nFree; /* Number of sqliteFree() calls */ int sqlite3_memUsed; /* TODO Total memory obtained from malloc */ int sqlite3_memMax; /* TODO Mem usage high-water mark */ int sqlite3_iMallocFail; /* Fail sqliteMalloc() after this many calls */ int sqlite3_iMallocReset = -1; /* When iMallocFail reaches 0, set to this */ /* ** Check for a simulated memory allocation failure. Return true if ** the failure should be simulated. Return false to proceed as normal. */ static int failMalloc(){ SqliteTsd *pTsd = sqlite3Tsd(); if( pTsd->isFail ){ return 1; } if( sqlite3_iMallocFail>=0 ){ sqlite3_iMallocFail--; if( sqlite3_iMallocFail==0 ){ sqlite3_iMallocFail = sqlite3_iMallocReset; pTsd->isFail = 1; return 1; } } return 0; } /* ** The argument is a pointer returned by sqlite3OsMalloc() or Realloc(). ** assert() that the first and last (TESTALLOC_NGUARD*4) bytes are set to the ** values set by the applyGuards() function. */ static void checkGuards(u32 *p) { int i; char *zAlloc = (char *)p; char *z; /* First set of guard words */ z = &zAlloc[TESTALLOC_OFFSET_GUARD1(p)]; for(i=0; i<TESTALLOC_NGUARD; i++){ assert(((u32 *)z)[i]==0xdead1122); } /* Second set of guard words */ z = &zAlloc[TESTALLOC_OFFSET_GUARD2(p)]; for(i=0; i<TESTALLOC_NGUARD; i++){ u32 guard = 0; memcpy(&guard, &z[i*sizeof(u32)], sizeof(u32)); assert(guard==0xdead3344); } } /* ** The argument is a pointer returned by sqlite3OsMalloc() or Realloc(). The ** first and last (TESTALLOC_NGUARD*4) bytes are set to known values for use as ** guard-posts. */ static void applyGuards(u32 *p) { int i; char *z; char *zAlloc = (char *)p; /* First set of guard words */ z = &zAlloc[TESTALLOC_OFFSET_GUARD1(p)]; for(i=0; i<TESTALLOC_NGUARD; i++){ ((u32 *)z)[i] = 0xdead1122; } /* Second set of guard words */ z = &zAlloc[TESTALLOC_OFFSET_GUARD2(p)]; for(i=0; i<TESTALLOC_NGUARD; i++){ static const int guard = 0xdead3344; memcpy(&z[i*sizeof(u32)], &guard, sizeof(u32)); } /* Line number */ z = &((char *)z)[TESTALLOC_NGUARD*sizeof(u32)]; /* Guard words */ z = &zAlloc[TESTALLOC_OFFSET_LINENUMBER(p)]; memcpy(z, &sqlite3Tsd()->iLine, sizeof(u32)); /* File name */ z = &zAlloc[TESTALLOC_OFFSET_FILENAME(p)]; strncpy(z, sqlite3Tsd()->zFile, TESTALLOC_FILESIZE); z[TESTALLOC_FILESIZE - 1] = '\0'; /* User string */ z = &zAlloc[TESTALLOC_OFFSET_USER(p)]; z[0] = 0; if( sqlite3_malloc_id ){ strncpy(z, sqlite3_malloc_id, TESTALLOC_USERSIZE); z[TESTALLOC_USERSIZE-1] = 0; } /* backtrace() stack */ z = &zAlloc[TESTALLOC_OFFSET_STACK(p)]; backtrace((void **)z, TESTALLOC_STACKFRAMES); /* Sanity check to make sure checkGuards() is working */ checkGuards(p); } static void *getOsPointer(void *p) { char *z = (char *)p; return (void *)(&z[-1 * TESTALLOC_OFFSET_DATA(p)]); } /* ** The argument points to an Os level allocation. Link it into the threads list ** of allocations. */ static void linkAlloc(void *p){ SqliteTsd *pTsd = sqlite3Tsd(); void **pp = (void **)p; pp[0] = 0; pp[1] = pTsd->pFirst; if( pTsd->pFirst ){ ((void **)pTsd->pFirst)[0] = p; } pTsd->pFirst = p; } /* ** The argument points to an Os level allocation. Unlinke it from the threads ** list of allocations. */ static void unlinkAlloc(void *p) { SqliteTsd *pTsd = sqlite3Tsd(); void **pp = (void **)p; if( p==pTsd->pFirst ){ assert(!pp[0]); assert(!pp[1] || ((void **)(pp[1]))[0]==p); pTsd->pFirst = pp[1]; if( pTsd->pFirst ){ ((void **)pTsd->pFirst)[0] = 0; } }else{ void **pprev = pp[0]; void **pnext = pp[1]; assert(pprev); assert(pprev[1]==p); pprev[1] = (void *)pnext; if( pnext ){ assert(pnext[0]==p); pnext[0] = (void *)pprev; } } } /* ** Pointer p is a pointer to an OS level allocation that has just been ** realloc()ed. Set the list pointers that point to this entry to it's new ** location. */ static void relinkAlloc(void *p) { void **pp = (void **)p; if( pp[0] ){ ((void **)(pp[0]))[1] = p; }else{ SqliteTsd *pTsd = sqlite3Tsd(); pTsd->pFirst = p; } if( pp[1] ){ ((void **)(pp[1]))[0] = p; } } /* ** This function sets the result of the Tcl interpreter passed as an argument ** to a list containing an entry for each currently outstanding call made to ** sqliteMalloc and friends by the current thread. ** ** Todo: We could have a version of this function that outputs to stdout, ** to debug memory leaks when Tcl is not available. */ #ifdef TCLSH #include <tcl.h> int sqlite3OutstandingMallocs(Tcl_Interp *interp){ void *p; SqliteTsd *pTsd = sqlite3Tsd(); Tcl_Obj *pRes = Tcl_NewObj(); Tcl_IncrRefCount(pRes); for(p=pTsd->pFirst; p; p=((void **)p)[1]){ Tcl_Obj *pEntry = Tcl_NewObj(); Tcl_Obj *pStack = Tcl_NewObj(); char *z; u32 iLine; int nBytes = sqlite3OsAllocationSize(p) - TESTALLOC_OVERHEAD; char *zAlloc = (char *)p; int i; Tcl_ListObjAppendElement(0, pEntry, Tcl_NewIntObj(nBytes)); z = &zAlloc[TESTALLOC_OFFSET_FILENAME(p)]; Tcl_ListObjAppendElement(0, pEntry, Tcl_NewStringObj(z, -1)); z = &zAlloc[TESTALLOC_OFFSET_LINENUMBER(p)]; memcpy(&iLine, z, sizeof(u32)); Tcl_ListObjAppendElement(0, pEntry, Tcl_NewIntObj(iLine)); z = &zAlloc[TESTALLOC_OFFSET_USER(p)]; Tcl_ListObjAppendElement(0, pEntry, Tcl_NewStringObj(z, -1)); z = &zAlloc[TESTALLOC_OFFSET_STACK(p)]; for(i=0; i<TESTALLOC_STACKFRAMES; i++){ char zHex[128]; sprintf(zHex, "%p", ((void **)z)[i]); Tcl_ListObjAppendElement(0, pStack, Tcl_NewStringObj(zHex, -1)); } Tcl_ListObjAppendElement(0, pEntry, pStack); Tcl_ListObjAppendElement(0, pRes, pEntry); } Tcl_ResetResult(interp); Tcl_SetObjResult(interp, pRes); Tcl_DecrRefCount(pRes); return TCL_OK; } #endif /* ** This is the test layer's wrapper around sqlite3OsMalloc(). */ static void * OSMALLOC(int n){ if( !failMalloc() ){ u32 *p; p = (u32 *)sqlite3OsMalloc(n + TESTALLOC_OVERHEAD); assert(p); sqlite3_nMalloc++; applyGuards(p); linkAlloc(p); return (void *)(&p[TESTALLOC_NGUARD + 2*sizeof(void *)/sizeof(u32)]); } return 0; } /* ** This is the test layer's wrapper around sqlite3OsFree(). The argument is a ** pointer to the space allocated for the application to use. */ void OSFREE(void *pFree){ u32 *p = (u32 *)getOsPointer(pFree); /* p points to Os level allocation */ checkGuards(p); unlinkAlloc(p); sqlite3OsFree(p); sqlite3_nFree++; } /* ** This is the test layer's wrapper around sqlite3OsRealloc(). */ void * OSREALLOC(void *pRealloc, int n){ if( !failMalloc() ){ u32 *p = (u32 *)getOsPointer(pRealloc); checkGuards(p); p = sqlite3OsRealloc(p, n + TESTALLOC_OVERHEAD); applyGuards(p); relinkAlloc(p); return (void *)(&p[TESTALLOC_NGUARD + 2*sizeof(void *)/sizeof(u32)]); } return 0; } void OSMALLOC_FAILED(){ sqlite3Tsd()->isFail = 0; } #else #define OSMALLOC(x) sqlite3OsMalloc(x) #define OSREALLOC(x,y) sqlite3OsRealloc(x,y) #define OSFREE(x) sqlite3OsFree(x) #define OSMALLOC_FAILED() #endif /* ** End code for memory allocation system test layer. **--------------------------------------------------------------------------*/ /* ** Allocate and return N bytes of uninitialised memory by calling ** sqlite3OsMalloc(). If the Malloc() call fails, attempt to free memory ** by calling sqlite3_release_memory(). */ void *sqlite3MallocRaw(int n){ SqliteTsd *pTsd = sqlite3Tsd(); void *p = 0; if( n>0 && !pTsd->mallocFailed ){ while( !(p = OSMALLOC(n)) && sqlite3_release_memory(n) ); if( !p ){ sqlite3Tsd()->mallocFailed = 1; OSMALLOC_FAILED(); } } return p; } /* ** Resize the allocation at p to n bytes by calling sqlite3OsRealloc(). The ** pointer to the new allocation is returned. If the Realloc() call fails, ** attempt to free memory by calling sqlite3_release_memory(). */ void *sqlite3Realloc(void *p, int n){ SqliteTsd *pTsd = sqlite3Tsd(); if( pTsd->mallocFailed ){ return 0; } if( !p ){ return sqlite3Malloc(n); }else{ void *np = 0; while( !(np = OSREALLOC(p, n)) && sqlite3_release_memory(n) ); if( !np ){ pTsd->mallocFailed = 1; OSMALLOC_FAILED(); } return np; } } /* ** Free the memory pointed to by p. p must be either a NULL pointer or a ** value returned by a previous call to sqlite3Malloc() or sqlite3Realloc(). */ void sqlite3FreeX(void *p){ if( p ){ OSFREE(p); } } /* ** A version of sqliteMalloc() that is always a function, not a macro. ** Currently, this is used only to alloc only used drawback. */ void *sqlite3MallocX(int n){ return sqliteMalloc(n); } /* ** sqlite3Malloc ** sqlite3ReallocOrFree ** ** These two are implemented as wrappers around sqlite3MallocRaw(), ** sqlite3Realloc() and sqlite3Free(). */ void *sqlite3Malloc(int n){ void *p = sqlite3MallocRaw(n); if( p ){ memset(p, 0, n); } return p; } void sqlite3ReallocOrFree(void **pp, int n){ void *p = sqlite3Realloc(*pp, n); if( !p ){ sqlite3FreeX(*pp); } *pp = p; } /* ** Make a copy of a string in memory obtained from sqliteMalloc(). These ** functions call sqlite3MallocRaw() directly instead of sqliteMalloc(). This ** is because when memory debugging is turned on, these two functions are ** called via macros that record the current file and line number in the ** SqliteTsd structure. */ char *sqlite3StrDup(const char *z){ char *zNew; if( z==0 ) return 0; zNew = sqlite3MallocRaw(strlen(z)+1); if( zNew ) strcpy(zNew, z); return zNew; } char *sqlite3StrNDup(const char *z, int n){ char *zNew; if( z==0 ) return 0; zNew = sqlite3MallocRaw(n+1); if( zNew ){ memcpy(zNew, z, n); zNew[n] = 0; } return zNew; } /* ** Create a string from the 2nd and subsequent arguments (up to the ** first NULL argument), store the string in memory obtained from ** sqliteMalloc() and make the pointer indicated by the 1st argument ** point to that string. The 1st argument must either be NULL or ** point to memory obtained from sqliteMalloc(). |
︙ | ︙ | |||
422 423 424 425 426 427 428 | *zResult = 0; va_start(ap, pz); while( (z = va_arg(ap, const char*))!=0 ){ strcpy(zResult, z); zResult += strlen(zResult); } va_end(ap); | < < < < < | 610 611 612 613 614 615 616 617 618 619 620 621 622 623 | *zResult = 0; va_start(ap, pz); while( (z = va_arg(ap, const char*))!=0 ){ strcpy(zResult, z); zResult += strlen(zResult); } va_end(ap); } /* ** Set the most recent error code and error string for the sqlite ** handle "db". The error code is set to "err_code". ** ** If it is not NULL, string zFormat specifies the format of the |
︙ | ︙ | |||
1022 1023 1024 1025 1026 1027 1028 | return p; } #endif /* ** Return a pointer to the SqliteTsd associated with the calling thread. */ | | > > > > > > > > > > > | > > > > > > > > | > > > > > > > > > > > | 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 | return p; } #endif /* ** Return a pointer to the SqliteTsd associated with the calling thread. */ static SqliteTsd tsd = { 0 /* mallocFailed flag */ #ifndef NDEBUG , 1 /* mallocAllowed flag */ #endif #ifndef SQLITE_MEMDEBUG , 0 , 0 , 0 , 0 #endif }; SqliteTsd *sqlite3Tsd(){ return &tsd; } void sqlite3MallocClearFailed(){ sqlite3Tsd()->mallocFailed = 0; } #ifndef NDEBUG /* ** This function sets a flag in the thread-specific-data structure that will ** cause an assert to fail if sqliteMalloc() or sqliteRealloc() is called. */ void sqlite3MallocDisallow(){ assert(sqlite3Tsd()->mallocAllowed); sqlite3Tsd()->mallocAllowed = 0; } /* ** This function clears the flag set in the thread-specific-data structure set ** by sqlite3MallocDisallow(). */ void sqlite3MallocAllow(){ assert(!sqlite3Tsd()->mallocAllowed); sqlite3Tsd()->mallocAllowed = 1; } #endif |
Changes to src/vacuum.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** This file contains code used to implement the VACUUM command. ** ** Most of the code in this file may be omitted by defining the ** SQLITE_OMIT_VACUUM macro. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** This file contains code used to implement the VACUUM command. ** ** Most of the code in this file may be omitted by defining the ** SQLITE_OMIT_VACUUM macro. ** ** $Id: vacuum.c,v 1.52 2005/12/09 14:25:09 danielk1977 Exp $ */ #include "sqliteInt.h" #include "vdbeInt.h" #include "os.h" #ifndef SQLITE_OMIT_VACUUM /* |
︙ | ︙ | |||
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 | ** by manually setting the autoCommit flag to true and detaching the ** vacuum database. The vacuum_db journal file is deleted when the pager ** is closed by the DETACH. */ db->autoCommit = 1; if( pDetach ){ ((Vdbe *)pDetach)->expired = 0; sqlite3_step(pDetach); rc2 = sqlite3_finalize(pDetach); if( rc==SQLITE_OK ){ rc = rc2; } } /* If one of the execSql() calls above returned SQLITE_NOMEM, then the ** mallocFailed flag will be clear (because execSql() calls sqlite3_exec()). ** Fix this so the flag and return code match. */ if( rc==SQLITE_NOMEM ){ | > > > > > | 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 | ** by manually setting the autoCommit flag to true and detaching the ** vacuum database. The vacuum_db journal file is deleted when the pager ** is closed by the DETACH. */ db->autoCommit = 1; if( pDetach ){ int mf = sqlite3Tsd()->mallocFailed; sqlite3Tsd()->mallocFailed = 0; sqlite3MallocDisallow(); ((Vdbe *)pDetach)->expired = 0; sqlite3_step(pDetach); rc2 = sqlite3_finalize(pDetach); if( rc==SQLITE_OK ){ rc = rc2; } sqlite3MallocAllow(); sqlite3Tsd()->mallocFailed = mf; } /* If one of the execSql() calls above returned SQLITE_NOMEM, then the ** mallocFailed flag will be clear (because execSql() calls sqlite3_exec()). ** Fix this so the flag and return code match. */ if( rc==SQLITE_NOMEM ){ |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
39 40 41 42 43 44 45 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** | | | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** ** $Id: vdbe.c,v 1.503 2005/12/09 14:25:09 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> #include "vdbeInt.h" /* |
︙ | ︙ | |||
386 387 388 389 390 391 392 393 394 395 | #endif #ifndef NDEBUG Mem *pStackLimit; #endif if( p->magic!=VDBE_MAGIC_RUN ) return SQLITE_MISUSE; assert( db->magic==SQLITE_MAGIC_BUSY ); assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY ); p->rc = SQLITE_OK; assert( p->explain==0 ); | > > > > > > < < | 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 | #endif #ifndef NDEBUG Mem *pStackLimit; #endif if( p->magic!=VDBE_MAGIC_RUN ) return SQLITE_MISUSE; assert( db->magic==SQLITE_MAGIC_BUSY ); pTos = p->pTos; if( p->rc==SQLITE_NOMEM ){ /* This happens if a malloc() inside a call to sqlite3_column_text() or ** sqlite3_column_text16() failed. */ goto no_mem; } assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY ); p->rc = SQLITE_OK; assert( p->explain==0 ); if( p->popStack ){ popStack(&pTos, p->popStack); p->popStack = 0; } p->resOnStack = 0; db->busyHandler.nBusy = 0; CHECK_FOR_INTERRUPT; |
︙ | ︙ | |||
3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 | pOp->p1, db->aDb[iDb].zName, zMaster, pOp->p3); if( zSql==0 ) goto no_mem; sqlite3SafetyOff(db); assert( db->init.busy==0 ); db->init.busy = 1; assert(0==sqlite3Tsd()->mallocFailed); rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0); db->init.busy = 0; sqlite3SafetyOn(db); if( rc==SQLITE_NOMEM ){ sqlite3Tsd()->mallocFailed = 1; goto no_mem; } | > < | 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 | pOp->p1, db->aDb[iDb].zName, zMaster, pOp->p3); if( zSql==0 ) goto no_mem; sqlite3SafetyOff(db); assert( db->init.busy==0 ); db->init.busy = 1; assert(0==sqlite3Tsd()->mallocFailed); rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0); sqliteFree(zSql); db->init.busy = 0; sqlite3SafetyOn(db); if( rc==SQLITE_NOMEM ){ sqlite3Tsd()->mallocFailed = 1; goto no_mem; } break; } #ifndef SQLITE_OMIT_ANALYZE /* Opcode: LoadAnalysis P1 * * ** ** Read the sqlite_stat1 table for database P1 and load the content |
︙ | ︙ |
Changes to src/vdbeapi.c.
︙ | ︙ | |||
237 238 239 240 241 242 243 | assert( p->aOp[p->nOp-1].p3!=0 ); assert( p->aOp[p->nOp-1].p3type==P3_DYNAMIC ); db->xProfile(db->pProfileArg, p->aOp[p->nOp-1].p3, elapseTime); } #endif sqlite3Error(p->db, rc, p->zErrMsg ? "%s" : 0, p->zErrMsg); | | | 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 | assert( p->aOp[p->nOp-1].p3!=0 ); assert( p->aOp[p->nOp-1].p3type==P3_DYNAMIC ); db->xProfile(db->pProfileArg, p->aOp[p->nOp-1].p3, elapseTime); } #endif sqlite3Error(p->db, rc, p->zErrMsg ? "%s" : 0, p->zErrMsg); sqlite3MallocClearFailed(); return rc; } /* ** Extract the user data from a sqlite3_context structure and return a ** pointer to it. */ |
︙ | ︙ | |||
373 374 375 376 377 378 379 380 381 382 383 384 385 | static Mem nullMem; if( nullMem.flags==0 ){ nullMem.flags = MEM_Null; } sqlite3Error(pVm->db, SQLITE_RANGE, 0); return &nullMem; } return &pVm->pTos[(1-vals)+i]; } /**************************** sqlite3_column_ ******************************* ** The following routines are used to access elements of the current row ** in the result set. */ const void *sqlite3_column_blob(sqlite3_stmt *pStmt, int i){ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > | > > | > > | > > | > > | > > | > > | > > | 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 | static Mem nullMem; if( nullMem.flags==0 ){ nullMem.flags = MEM_Null; } sqlite3Error(pVm->db, SQLITE_RANGE, 0); return &nullMem; } return &pVm->pTos[(1-vals)+i]; } /* ** This function is called after invoking an sqlite3_value_XXX function on a ** column value (i.e. a value returned by evaluating an SQL expression in the ** select list of a SELECT statement) that may cause a malloc() failure. If ** malloc() has failed, the threads mallocFailed flag is cleared and the result ** code of statement pStmt set to SQLITE_NOMEM. ** ** Specificly, this is called from within: ** ** sqlite3_column_int() ** sqlite3_column_int64() ** sqlite3_column_text() ** sqlite3_column_text16() ** sqlite3_column_real() ** sqlite3_column_bytes() ** sqlite3_column_bytes16() ** ** But not for sqlite3_column_blob(), which never calls malloc(). */ static void columnMallocFailure(sqlite3_stmt *pStmt) { /* If malloc() failed during an encoding conversion within an ** sqlite3_column_XXX API, then set the return code of the statement to ** SQLITE_NOMEM. The next call to _step() (if any) will return SQLITE_ERROR ** and _finalize() will return NOMEM. */ if( sqlite3Tsd()->mallocFailed ){ ((Vdbe *)pStmt)->rc = SQLITE_NOMEM; sqlite3MallocClearFailed(); } } /**************************** sqlite3_column_ ******************************* ** The following routines are used to access elements of the current row ** in the result set. */ const void *sqlite3_column_blob(sqlite3_stmt *pStmt, int i){ const void *val; sqlite3MallocDisallow(); val = sqlite3_value_blob( columnMem(pStmt,i) ); sqlite3MallocAllow(); return val; } int sqlite3_column_bytes(sqlite3_stmt *pStmt, int i){ int val = sqlite3_value_bytes( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val; } int sqlite3_column_bytes16(sqlite3_stmt *pStmt, int i){ int val = sqlite3_value_bytes16( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val; } double sqlite3_column_double(sqlite3_stmt *pStmt, int i){ double val = sqlite3_value_double( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val; } int sqlite3_column_int(sqlite3_stmt *pStmt, int i){ int val = sqlite3_value_int( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val; } sqlite_int64 sqlite3_column_int64(sqlite3_stmt *pStmt, int i){ sqlite_int64 val = sqlite3_value_int64( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val; } const unsigned char *sqlite3_column_text(sqlite3_stmt *pStmt, int i){ const unsigned char *val = sqlite3_value_text( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val; } #if 0 sqlite3_value *sqlite3_column_value(sqlite3_stmt *pStmt, int i){ return columnMem(pStmt, i); } #endif #ifndef SQLITE_OMIT_UTF16 const void *sqlite3_column_text16(sqlite3_stmt *pStmt, int i){ const void *val = sqlite3_value_text16( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val; } #endif /* SQLITE_OMIT_UTF16 */ int sqlite3_column_type(sqlite3_stmt *pStmt, int i){ return sqlite3_value_type( columnMem(pStmt,i) ); } /* |
︙ | ︙ | |||
448 449 450 451 452 453 454 | } N += useType*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. */ | | < | 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 | } N += useType*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. */ sqlite3MallocClearFailed(); return ret; } /* ** Return the name of the Nth column of the result set returned by SQL ** statement pStmt. */ const char *sqlite3_column_name(sqlite3_stmt *pStmt, int N){ return columnName(pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, 0); |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
411 412 413 414 415 416 417 | ** the Vdbe. In these cases we can just copy the pointer. ** ** If addr<0 then change P3 on the most recently inserted instruction. */ void sqlite3VdbeChangeP3(Vdbe *p, int addr, const char *zP3, int n){ Op *pOp; assert( p->magic==VDBE_MAGIC_INIT ); | | | 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 | ** the Vdbe. In these cases we can just copy the pointer. ** ** If addr<0 then change P3 on the most recently inserted instruction. */ void sqlite3VdbeChangeP3(Vdbe *p, int addr, const char *zP3, int n){ Op *pOp; assert( p->magic==VDBE_MAGIC_INIT ); if( p==0 || p->aOp==0 || sqlite3Tsd()->mallocFailed ){ if (n != P3_KEYINFO) { freeP3(n, (void*)*(char**)&zP3); } return; } if( addr<0 || addr>=p->nOp ){ addr = p->nOp - 1; |
︙ | ︙ | |||
466 467 468 469 470 471 472 | /* ** Replace the P3 field of the most recently coded instruction with ** comment text. */ void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){ va_list ap; assert( p->nOp>0 ); | | | 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 | /* ** Replace the P3 field of the most recently coded instruction with ** comment text. */ void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){ va_list ap; assert( p->nOp>0 ); assert( p->aOp==0 || p->aOp[p->nOp-1].p3==0 || sqlite3Tsd()->mallocFailed ); va_start(ap, zFormat); sqlite3VdbeChangeP3(p, -1, sqlite3VMPrintf(zFormat, ap), P3_DYNAMIC); va_end(ap); } #endif /* |
︙ | ︙ |
Changes to test/malloc3.test.
︙ | ︙ | |||
9 10 11 12 13 14 15 | # #*********************************************************************** # # 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. # | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | # #*********************************************************************** # # 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.4 2005/12/09 14:25:12 danielk1977 Exp $ 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..." |
︙ | ︙ | |||
576 577 578 579 580 581 582 583 584 585 586 587 588 | # puts "PREP $iterid $v" db eval $v incr pc } default { error "Unknown switch: $k" } } } } # Turn of the Tcl interface's prepared statement caching facility. db cache size 0 | > | | > > > > | 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 | # puts "PREP $iterid $v" db eval $v incr pc } default { error "Unknown switch: $k" } } # if {$iFail > ($iFailStart+1)} return } } # Turn of the Tcl interface's prepared statement caching facility. db cache size 0 run_test $::run_test_script # run_test [lrange $::run_test_script 0 3] 0 63 sqlite_malloc_fail 0 db close pp_check_for_leaks finish_test |
Changes to test/malloc4.test.
︙ | ︙ | |||
8 9 10 11 12 13 14 | # 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. # | | > > > > < > > > > > > > > > > > > | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | # 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.2 2005/12/09 14:25:12 danielk1977 Exp $ #--------------------------------------------------------------------------- # NOTES ON EXPECTED BEHAVIOUR # # [193] When a memory allocation failure occurs during sqlite3_column_name(), # sqlite3_column_name16(), sqlite3_column_decltype(), or # sqlite3_column_decltype16() the function shall return NULL. # #--------------------------------------------------------------------------- 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. # # ${testid}.2.1 - Call _name() # ${testid}.2.2 - Call _name16() # ${testid}.2.3 - Call _name() # ${testid}.2.4 - Check that the return values of the above three calls are # consistent with each other and with the simulated # malloc() failures. # # Because the code that implements the _decltype() and _decltype16() APIs # is the same as the _name() and _name16() implementations, we don't worry # about explicitly testing them. # 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 { |
︙ | ︙ | |||
74 75 76 77 78 79 80 | $::name8 == $::name8_2 && $::name16 == $::name8 && !$::mallocFailed || $::name8 == $::name8_2 && $::name16 == "" && $::mallocFailed || $::name8 == $::name16 && $::name8_2 == "" && $::mallocFailed || $::name8_2 == $::name16 && $::name8 == "" && $::mallocFailed } } {1} | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | < < < < < < < < < < < < < < < < < > > > > | 89 90 91 92 93 94 95 96 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 136 137 138 139 140 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 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 | $::name8 == $::name8_2 && $::name16 == $::name8 && !$::mallocFailed || $::name8 == $::name8_2 && $::name16 == "" && $::mallocFailed || $::name8 == $::name16 && $::name8_2 == "" && $::mallocFailed || $::name8_2 == $::name16 && $::name8 == "" && $::mallocFailed } } {1} # Step the statement so that we can call _text() and _text16(). Before # running sqlite3_step(), make sure that malloc() is not about to fail. # Memory allocation failures that occur within sqlite3_step() are tested # elsewhere. set mf [lindex [sqlite_malloc_stat] 2] sqlite_malloc_fail 0 do_test ${testid}.3 { sqlite3_step $::STMT } {SQLITE_ROW} sqlite_malloc_fail $mf # Test for malloc() failures within _text() and _text16(). # do_test ${testid}.4.1 { set ::text8 [sqlite3_column_text $::STMT 0] set mf [expr [lindex [sqlite_malloc_stat] 2] <= 0 && !$::mallocFailed] expr {$mf==0 || $::text8 == ""} } {1} do_test ${testid}.4.2 { set ::text16 [sqlite3_column_text16 $::STMT 0] set ::text16 [encoding convertfrom unicode $::text16] set ::text16 [string range $::text16 0 end-1] set mf [expr [lindex [sqlite_malloc_stat] 2] <= 0 && !$::mallocFailed] expr {$mf==0 || $::text16 == ""} } {1} do_test ${testid}.4.3 { set ::text8_2 [sqlite3_column_text $::STMT 0] set mf [expr [lindex [sqlite_malloc_stat] 2] <= 0 && !$::mallocFailed] expr {$mf==0 || $::text8_2 == "" || ($::text16 == "" && $::text8 != "")} } {1} # Test for malloc() failures within _int(), _int64() and _real(). The only # way this can occur is if the string has to be translated from UTF-16 to # UTF-8 before being converted to a numeric value. do_test ${testid}.4.4.1 { set mf [lindex [sqlite_malloc_stat] 2] sqlite_malloc_fail 0 sqlite3_column_text16 $::STMT 0 sqlite_malloc_fail $mf sqlite3_column_int $::STMT 0 } {0} do_test ${testid}.4.5 { set mf [lindex [sqlite_malloc_stat] 2] sqlite_malloc_fail 0 sqlite3_column_text16 $::STMT 0 sqlite_malloc_fail $mf sqlite3_column_int64 $::STMT 0 } {0} do_test ${testid}.4.6 { set mf [lindex [sqlite_malloc_stat] 2] sqlite_malloc_fail 0 sqlite3_column_text16 $::STMT 0 sqlite_malloc_fail $mf sqlite3_column_double $::STMT 0 } {0.0} set mallocFailedAfterStep [expr \ [lindex [sqlite_malloc_stat] 2] <= 0 && !$::mallocFailed ] sqlite_malloc_fail 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_DONE. # do_test ${testid}.5 { sqlite3_step $::STMT } [expr {$mallocFailedAfterStep ? "SQLITE_ERROR" : "SQLITE_DONE"}] do_test ${testid}.6 { sqlite3_finalize $::STMT } [expr {$mallocFailedAfterStep ? "SQLITE_NOMEM" : "SQLITE_OK"}] if {$::mallocFailed == 0 && $mallocFailedAfterStep == 0} { sqlite_malloc_fail 0 set go 0 } } } execsql { CREATE TABLE tbl( the_first_reasonably_long_column_name that_also_has_quite_a_lengthy_type ); INSERT INTO tbl VALUES( 'An extra long string. Far too long to be stored in NBFS bytes.' ); } do_stmt_test 1 "SELECT * FROM tbl" sqlite_malloc_fail 0 finish_test |
Changes to test/select1.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 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. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the SELECT statement. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 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. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the SELECT statement. # # $Id: select1.test,v 1.44 2005/12/09 14:25:12 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Try to select on a non-existant table. # do_test select1-1.1 { |
︙ | ︙ | |||
794 795 796 797 798 799 800 801 | execsql2 { SELECT z.x FROM ( SELECT a,b FROM t3 UNION SELECT a AS 'x', b AS 'y' FROM t4 ORDER BY a,b ) AS 'z' ORDER BY x; } } {x 1 x 3} } ;# ifcapable compound | < | 794 795 796 797 798 799 800 801 802 | execsql2 { SELECT z.x FROM ( SELECT a,b FROM t3 UNION SELECT a AS 'x', b AS 'y' FROM t4 ORDER BY a,b ) AS 'z' ORDER BY x; } } {x 1 x 3} } ;# ifcapable compound finish_test |
Changes to test/tester.tcl.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 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. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements some common TCL routines used for regression # testing the SQLite library # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 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. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements some common TCL routines used for regression # testing the SQLite library # # $Id: tester.tcl,v 1.53 2005/12/09 14:25:12 danielk1977 Exp $ # Make sure tclsqlite3 was compiled correctly. Abort now with an # error message if not. # if {[sqlite3 -tcl-uses-utf]} { if {"\u1234"=="u1234"} { puts stderr "***** BUILD PROBLEM *****" |
︙ | ︙ | |||
79 80 81 82 83 84 85 86 87 88 89 90 91 92 | set failList {} set maxErr 1000 # Invoke the do_test procedure to run a single test # proc do_test {name cmd expected} { global argv nErr nTest skip_test maxErr if {$skip_test} { set skip_test 0 return } if {[llength $argv]==0} { set go 1 } else { | > | 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | set failList {} set maxErr 1000 # Invoke the do_test procedure to run a single test # proc do_test {name cmd expected} { global argv nErr nTest skip_test maxErr set ::sqlite_malloc_id $name if {$skip_test} { set skip_test 0 return } if {[llength $argv]==0} { set go 1 } else { |
︙ | ︙ | |||
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | # proc finish_test {} { finalize_testing } proc finalize_testing {} { global nTest nErr nProb sqlite_open_file_count if {$nErr==0} memleak_check catch {db close} puts "$nErr errors out of $nTest tests" puts "Failures on these tests: $::failList" if {$nProb>0} { puts "$nProb probabilistic tests also failed, but this does" puts "not necessarily indicate a malfunction." } if 0 { | > > > > > > | 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | # proc finish_test {} { finalize_testing } proc finalize_testing {} { global nTest nErr nProb sqlite_open_file_count if {$nErr==0} memleak_check catch {db close} catch {db2 close} catch {db3 close} pp_check_for_leaks puts "$nErr errors out of $nTest tests" puts "Failures on these tests: $::failList" if {$nProb>0} { puts "$nProb probabilistic tests also failed, but this does" puts "not necessarily indicate a malfunction." } if 0 { |
︙ | ︙ | |||
418 419 420 421 422 423 424 425 426 427 428 | set t [open $to w] fconfigure $t -translation binary puts -nonewline $t [read $f [file size $from]] close $t close $f } } # If the library is compiled with the SQLITE_DEFAULT_AUTOVACUUM macro set # to non-zero, then set the global variable $AUTOVACUUM to 1. set AUTOVACUUM $sqlite_options(default_autovacuum) | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 | set t [open $to w] fconfigure $t -translation binary puts -nonewline $t [read $f [file size $from]] close $t close $f } } # This command checks for outstanding calls to sqliteMalloc() from within # the current thread. A list is returned with one entry for each outstanding # malloc. Each list entry is itself a list of 5 items, as follows: # # { <number-bytes> <file-name> <line-number> <test-case> <stack-dump> } # proc check_for_leaks {} { set ret [list] foreach alloc [sqlite_malloc_outstanding] { foreach {nBytes file iLine userstring backtrace} $alloc {} set stack [list] set skip 0 # The first command in this block will probably fail on windows. This # means there will be no stack dump available. catch { set stuff [eval "exec addr2line -e ./testfixture -f $backtrace"] foreach {func line} $stuff { if {$func != "??" || $line != "??:0"} { regexp {.*/(.*)} $line dummy line lappend stack "${func}() $line" } else { if {[lindex $stack end] != "..."} { lappend stack "..." } } } } if {!$skip} { lappend ret [list $nBytes $file $iLine $userstring $stack] } } return $ret } # Pretty print a report based on the return value of [check_for_leaks] to # stdout. proc pp_check_for_leaks {} { set l [check_for_leaks] set n 0 foreach leak $l { foreach {nBytes file iLine userstring stack} $leak {} puts "$nBytes bytes leaked at $file:$iLine ($userstring)" foreach frame $stack { puts " $frame" } incr n $nBytes } puts "Memory leaked: $n bytes in [llength $l] allocations" puts "" } # If the library is compiled with the SQLITE_DEFAULT_AUTOVACUUM macro set # to non-zero, then set the global variable $AUTOVACUUM to 1. set AUTOVACUUM $sqlite_options(default_autovacuum) |