Index: src/btree.c ================================================================== --- src/btree.c +++ src/btree.c @@ -7,11 +7,11 @@ ** 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. ** ************************************************************************* -** $Id: btree.c,v 1.230 2005/01/11 10:25:07 danielk1977 Exp $ +** $Id: btree.c,v 1.231 2005/01/12 07:15:05 danielk1977 Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to ** ** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3: @@ -4741,16 +4741,15 @@ int sqlite3BtreeFlags(BtCursor *pCur){ MemPage *pPage = pCur->pPage; return pPage ? pPage->aData[pPage->hdrOffset] : 0; } +#ifdef SQLITE_DEBUG /* ** Print a disassembly of the given page on standard output. This routine ** is used for debugging and testing only. */ -#ifdef SQLITE_TEST -#ifndef SQLITE_OMIT_BTREEPAGEDUMP static int btreePageDump(Btree *pBt, int pgno, int recursive, MemPage *pParent){ int rc; MemPage *pPage; int i, j, c; int nFree; @@ -4843,15 +4842,12 @@ pPage->isInit = isInit; sqlite3pager_unref(data); fflush(stdout); return SQLITE_OK; } -#endif int sqlite3BtreePageDump(Btree *pBt, int pgno, int recursive){ -#ifndef SQLITE_OMIT_BTREEPAGEDUMP return btreePageDump(pBt, pgno, recursive, 0); -#endif } #endif #ifdef SQLITE_TEST /* Index: src/btree.h ================================================================== --- src/btree.h +++ src/btree.h @@ -11,11 +11,11 @@ ************************************************************************* ** This header file defines the interface that the sqlite B-Tree file ** subsystem. See comments in the source code for a detailed description ** of what each interface routine does. ** -** @(#) $Id: btree.h,v 1.60 2004/11/05 15:45:10 danielk1977 Exp $ +** @(#) $Id: btree.h,v 1.61 2005/01/12 07:15:05 danielk1977 Exp $ */ #ifndef _BTREE_H_ #define _BTREE_H_ /* TODO: This definition is just included so other modules compile. It @@ -125,10 +125,14 @@ #ifdef SQLITE_TEST int sqlite3BtreeCursorInfo(BtCursor*, int*, int); void sqlite3BtreeCursorList(Btree*); -int sqlite3BtreePageDump(Btree*, int, int recursive); #endif +#ifdef SQLITE_DEBUG +int sqlite3BtreePageDump(Btree*, int, int recursive); +#else +#define sqlite3BtreePageDump(X,Y,Z) SQLITE_OK +#endif #endif /* _BTREE_H_ */ Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -9,11 +9,11 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.351 2005/01/08 18:42:28 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.352 2005/01/12 07:15:05 danielk1977 Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ /* @@ -229,11 +229,11 @@ ** ** and a line of text will be written to standard error for ** each malloc() and free(). This output can be analyzed ** by an AWK script to determine if there are any leaks. */ -#ifdef SQLITE_DEBUG +#ifdef SQLITE_TEST # define sqliteMalloc(X) sqlite3Malloc_(X,1,__FILE__,__LINE__) # define sqliteMallocRaw(X) sqlite3Malloc_(X,0,__FILE__,__LINE__) # define sqliteFree(X) sqlite3Free_(X,__FILE__,__LINE__) # define sqliteRealloc(X,Y) sqlite3Realloc_(X,Y,__FILE__,__LINE__) # define sqliteStrDup(X) sqlite3StrDup_(X,__FILE__,__LINE__) @@ -255,11 +255,11 @@ /* ** The following global variables are used for testing and debugging ** only. They only work if SQLITE_DEBUG is defined. */ -#ifdef SQLITE_DEBUG +#ifdef SQLITE_TEST 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 */ #endif @@ -1278,11 +1278,11 @@ 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 *); -#ifdef SQLITE_DEBUG +#ifdef SQLITE_TEST void *sqlite3Malloc_(int,int,char*,int); void sqlite3Free_(void*,char*,int); void *sqlite3Realloc_(void*,int,char*,int); char *sqlite3StrDup_(const char*,char*,int); char *sqlite3StrNDup_(const char*, int,char*,int); Index: src/test1.c ================================================================== --- src/test1.c +++ src/test1.c @@ -11,11 +11,11 @@ ************************************************************************* ** 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.119 2005/01/11 16:54:15 drh Exp $ +** $Id: test1.c,v 1.120 2005/01/12 07:15:05 danielk1977 Exp $ */ #include "sqliteInt.h" #include "tcl.h" #include "os.h" #include @@ -754,11 +754,11 @@ ** first failure will continue to fail on every call. If REPEAT-INTERVAL is ** 2 then every other malloc will fail. And so forth. ** ** Turn off this mechanism and reset the sqlite3_malloc_failed variable is N==0. */ -#ifdef SQLITE_DEBUG +#ifdef SQLITE_TEST static int sqlite_malloc_fail( void *NotUsed, Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ char **argv /* Text of each argument */ @@ -785,11 +785,11 @@ /* ** Usage: sqlite_malloc_stat ** ** Return the number of prior calls to sqliteMalloc() and sqliteFree(). */ -#ifdef SQLITE_DEBUG +#ifdef SQLITE_TEST static int sqlite_malloc_stat( void *NotUsed, Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ char **argv /* Text of each argument */ @@ -2747,11 +2747,11 @@ { "sqlite3_close", (Tcl_CmdProc*)sqlite_test_close }, { "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_DEBUG +#ifdef SQLITE_TEST { "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 }, Index: src/utf.c ================================================================== --- src/utf.c +++ src/utf.c @@ -10,11 +10,11 @@ ** ************************************************************************* ** This file contains routines used to translate between UTF-8, ** UTF-16, UTF-16BE, and UTF-16LE. ** -** $Id: utf.c,v 1.30 2004/11/14 21:56:30 drh Exp $ +** $Id: utf.c,v 1.31 2005/01/12 07:15:06 danielk1977 Exp $ ** ** Notes on UTF-8: ** ** Byte-0 Byte-1 Byte-2 Byte-3 Value ** 0xxxxxxx 00000000 00000000 0xxxxxxx @@ -250,11 +250,11 @@ assert( pMem->flags&MEM_Str ); assert( pMem->enc!=desiredEnc ); assert( pMem->enc!=0 ); assert( pMem->n>=0 ); -#ifdef TRANSLATE_TRACE +#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG) { char zBuf[100]; sqlite3VdbeMemPrettyPrint(pMem, zBuf, 100); fprintf(stderr, "INPUT: %s\n", zBuf); } @@ -366,11 +366,11 @@ pMem->flags |= (MEM_Term|MEM_Dyn); } pMem->z = zOut; translate_out: -#ifdef TRANSLATE_TRACE +#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG) { char zBuf[100]; sqlite3VdbeMemPrettyPrint(pMem, zBuf, 100); fprintf(stderr, "OUTPUT: %s\n", zBuf); } Index: src/util.c ================================================================== --- src/util.c +++ src/util.c @@ -12,11 +12,11 @@ ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** -** $Id: util.c,v 1.124 2005/01/11 15:28:33 drh Exp $ +** $Id: util.c,v 1.125 2005/01/12 07:15:06 danielk1977 Exp $ */ #include "sqliteInt.h" #include #include @@ -42,14 +42,14 @@ ** This causes the library to abort and never again function. */ int sqlite3_malloc_failed = 0; /* -** If SQLITE_DEBUG is defined, then use versions of malloc() and +** If SQLITE_TEST is defined, then use versions of malloc() and ** free() that track memory usage and check for buffer overruns. */ -#ifdef SQLITE_DEBUG +#ifdef SQLITE_TEST /* ** 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 @@ -249,11 +249,11 @@ /* ** The following versions of malloc() and free() are for use in a ** normal build. */ -#if !defined(SQLITE_DEBUG) +#if !defined(SQLITE_TEST) /* ** Allocate new memory and set it to zero. Return NULL if ** no memory is available. See also sqliteMallocRaw(). */ @@ -327,11 +327,11 @@ memcpy(zNew, z, n); zNew[n] = 0; } return zNew; } -#endif /* !defined(SQLITE_DEBUG) */ +#endif /* !defined(SQLITE_TEST) */ /* ** 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 Index: src/vdbe.c ================================================================== --- src/vdbe.c +++ src/vdbe.c @@ -41,11 +41,11 @@ ** 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.440 2005/01/11 13:02:34 danielk1977 Exp $ +** $Id: vdbe.c,v 1.441 2005/01/12 07:15:06 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" #include #include "vdbeInt.h" @@ -301,11 +301,11 @@ } } } } -#ifndef NDEBUG +#ifdef SQLITE_DEBUG /* ** Write a nice string representation of the contents of cell pMem ** into buffer zBuf, length nBuf. */ void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf, int nBuf){ @@ -4517,10 +4517,12 @@ } if( pc<-1 || pc>=p->nOp ){ sqlite3SetString(&p->zErrMsg, "jump destination out of range", (char*)0); rc = SQLITE_INTERNAL; } +#ifdef SQLITE_DEBUG + /* Code for tracing the vdbe stack. */ if( p->trace && pTos>=p->aStack ){ int i; fprintf(p->trace, "Stack:"); for(i=0; i>-5 && &pTos[i]>=p->aStack; i--){ if( pTos[i].flags & MEM_Null ){ @@ -4539,11 +4541,12 @@ } } if( rc!=0 ) fprintf(p->trace," rc=%d",rc); fprintf(p->trace,"\n"); } -#endif +#endif /* SQLITE_DEBUG */ +#endif /* NDEBUG */ } /* The end of the for(;;) loop the loops through opcodes */ /* If we reach this point, it means that execution is finished. */ vdbe_halt: Index: src/vdbemem.c ================================================================== --- src/vdbemem.c +++ src/vdbemem.c @@ -392,10 +392,12 @@ pMem->enc = enc; pMem->type = enc==0 ? SQLITE_BLOB : SQLITE_TEXT; pMem->n = n; + assert( enc==0 || enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE + || enc==SQLITE_UTF16BE ); switch( enc ){ case 0: pMem->flags |= MEM_Blob; break; @@ -416,15 +418,11 @@ pMem->flags |= MEM_Term; } if( sqlite3VdbeMemHandleBom(pMem) ){ return SQLITE_NOMEM; } - break; #endif /* SQLITE_OMIT_UTF16 */ - - default: - assert(0); } if( pMem->flags&MEM_Ephem ){ return sqlite3VdbeMemMakeWriteable(pMem); } return SQLITE_OK; Index: test/all.test ================================================================== --- test/all.test +++ test/all.test @@ -8,11 +8,11 @@ # May you share freely, never taking more than you give. # #*********************************************************************** # This file runs all tests. # -# $Id: all.test,v 1.25 2005/01/08 02:35:44 danielk1977 Exp $ +# $Id: all.test,v 1.26 2005/01/12 07:15:07 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl rename finish_test really_finish_test proc finish_test {} {memleak_check} @@ -53,11 +53,10 @@ autovacuum_crash.test quick.test malloc.test misuse.test memleak.test - corrupt.test } # Test files btree2.test and btree4.test don't work if the # SQLITE_DEFAULT_AUTOVACUUM macro is defined to true (because they depend # on tables being allocated starting at page 2). Index: test/malloc.test ================================================================== --- test/malloc.test +++ test/malloc.test @@ -12,11 +12,11 @@ # When compiled with -DSQLITE_DEBUG=1, the SQLite library accepts a special # command (sqlite_malloc_fail N) 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.13 2005/01/11 13:02:34 danielk1977 Exp $ +# $Id: malloc.test,v 1.14 2005/01/12 07:15:07 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Only run these tests if memory debugging is turned on. @@ -314,14 +314,17 @@ execsql { CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2); INSERT INTO t1 VALUES(3, 4); INSERT INTO t1 VALUES(5, 6); + INSERT INTO t1 VALUES(7, randstr(1200,1200)); } sqlite_malloc_fail $i set v [catch {execsql { - SELECT min(a) FROM t1 GROUP BY b; + SELECT min(a) FROM t1 WHERE a<6 GROUP BY b; + SELECT a FROM t1 WHERE a<6 ORDER BY a; + SELECT b FROM t1 WHERE a>6; }} msg] set leftover [lindex [sqlite_malloc_stat] 2] if {$leftover>0} { if {$leftover>1} {puts "\nLeftover: $leftover\nReturn=$v Message=$msg"} set ::go 0 @@ -331,14 +334,59 @@ if {!$v2} {puts "\nError message returned: $msg"} lappend v $v2 } } {1 1} } + +# This block is designed to test that some malloc failures that may +# occur in vdbeapi.c. Specifically, if a malloc failure that occurs +# when converting UTF-16 text to integers and real numbers is handled +# correctly. +# +# This doesn't actually return an error to the user. That could be +# viewed as a bug. +# +for {set go 1; set i 1} {$go && $::sqlite_options(utf16)} {incr i} { + do_test malloc-8.$i { + sqlite_malloc_fail 0 + catch {db close} + catch {file delete -force test.db} + catch {file delete -force test.db-journal} + + set ::DB [sqlite3 db test.db] + set sql "SELECT '[string repeat abc 20]', '[string repeat def 20]', ?" + set ::STMT [sqlite3_prepare $::DB $sql -1 X] + sqlite3_step $::STMT + + if { $::tcl_platform(byteOrder)=="littleEndian" } { + set ::bomstr "\xFF\xFE" + } else { + set ::bomstr "\xFE\xFF" + } + append ::bomstr [encoding convertto unicode "123456789_123456789_12345678"] + + sqlite_malloc_fail $i + catch { + sqlite3_column_text16 $::STMT 0 + sqlite3_column_int $::STMT 0 + sqlite3_column_text16 $::STMT 1 + sqlite3_column_double $::STMT 1 + sqlite3_reset $::STMT + sqlite3_bind_text16 $::STMT 1 $::bomstr 60 + + } msg + sqlite3_finalize $::STMT + if {[lindex [sqlite_malloc_stat] 2]>0} { + set ::go 0 + } + expr 0 + } {0} +} # Ensure that no file descriptors were leaked. -do_test malloc-6.X { +do_test malloc-99.X { catch {db close} set sqlite_open_file_count } {0} sqlite_malloc_fail 0 finish_test