From: drh Date: Fri, 24 Apr 2015 23:45:23 +0000 (+0000) Subject: Add the --oom option to fuzzershell. X-Git-Tag: version-3.8.10~51 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=048810b63b29762033c677488fd0b6b68c1294aa;p=thirdparty%2Fsqlite.git Add the --oom option to fuzzershell. FossilOrigin-Name: 14a9e4a377bf2974f5db148c8f86e2c5ffdfa28d --- diff --git a/manifest b/manifest index d8496c7409..1418aef9a3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sfuzzershell\sso\sthat\sit\sworks\swith\sSQLITE_OMIT_TRACE. -D 2015-04-24T18:31:12.676 +C Add\sthe\s--oom\soption\sto\sfuzzershell. +D 2015-04-24T23:45:23.568 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 31b38b9da2e4b36f54a013bd71a5c3f6e45ca78f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -1205,7 +1205,7 @@ F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b F tool/extract.c 054069d81b095fbdc189a6f5d4466e40380505e2 F tool/fast_vacuum.c 5ba0d6f5963a0a63bdc42840f678bad75b2ebce1 F tool/fragck.tcl 5265a95126abcf6ab357f7efa544787e5963f439 -F tool/fuzzershell.c a13c48cb83bbea8966442d777e14595b87023701 +F tool/fuzzershell.c 96fb9b18a3e77777290b59bee9a2759dab3a8ef9 F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4 F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce @@ -1253,7 +1253,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 4dda916a572bcb54c8cf3b81d965328632a722eb -R fafcb3fcae40447c0604a45203b7a18d +P dc88fe7e641c52d27fba8c753cee590db87388c5 +R b6b6b08ed6fc824093828aadd4063979 U drh -Z 443a2106b8aed7f08a3ed861aaf1e388 +Z 5f3b959ee8a94e01f097246d319ba4ca diff --git a/manifest.uuid b/manifest.uuid index f42387d8b9..18bce80616 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -dc88fe7e641c52d27fba8c753cee590db87388c5 \ No newline at end of file +14a9e4a377bf2974f5db148c8f86e2c5ffdfa28d \ No newline at end of file diff --git a/tool/fuzzershell.c b/tool/fuzzershell.c index 51f1a63660..5c0da82a43 100644 --- a/tool/fuzzershell.c +++ b/tool/fuzzershell.c @@ -71,11 +71,51 @@ ** All global variables are gathered into the "g" singleton. */ struct GlobalVars { - const char *zArgv0; /* Name of program */ + const char *zArgv0; /* Name of program */ + sqlite3_mem_methods sOrigMem; /* Original memory methods */ + sqlite3_mem_methods sOomMem; /* Memory methods with OOM simulator */ + int iOomCntdown; /* Memory fails on 1 to 0 transition */ + int nOomFault; /* Increments for each OOM fault */ + int bOomOnce; /* Fail just once if true */ + int bOomEnable; /* True to enable OOM simulation */ + int nOomBrkpt; /* Number of calls to oomFault() */ } g; +/* +** This routine is called when a simulated OOM occurs. It exists as a +** convenient place to set a debugger breakpoint. +*/ +static void oomFault(void){ + g.nOomBrkpt++; +} +/* Versions of malloc() and realloc() that simulate OOM conditions */ +static void *oomMalloc(int nByte){ + if( nByte>0 && g.bOomEnable && g.iOomCntdown>0 ){ + g.iOomCntdown--; + if( g.iOomCntdown==0 ){ + if( g.nOomFault==0 ) oomFault(); + g.nOomFault++; + if( !g.bOomOnce ) g.iOomCntdown = 1; + return 0; + } + } + return g.sOrigMem.xMalloc(nByte); +} +static void *oomRealloc(void *pOld, int nByte){ + if( nByte>0 && g.bOomEnable && g.iOomCntdown>0 ){ + g.iOomCntdown--; + if( g.iOomCntdown==0 ){ + if( g.nOomFault==0 ) oomFault(); + g.nOomFault++; + if( !g.bOomOnce ) g.iOomCntdown = 1; + return 0; + } + } + return g.sOrigMem.xRealloc(pOld, nByte); +} + /* ** Print an error message and abort in such a way to indicate to the ** fuzzer that this counts as a crash. @@ -259,6 +299,7 @@ static void showHelp(void){ " --help Show this help text\n" " --initdb DBFILE Initialize the in-memory database using template DBFILE\n" " --lookaside N SZ Configure lookaside for N slots of SZ bytes each\n" +" --oom Run each test multiple times in a simulated OOM loop\n" " --pagesize N Set the page size to N\n" " --pcache N SZ Configure N pages of pagecache each of size SZ bytes\n" " -q Reduced output\n" @@ -376,8 +417,13 @@ int main(int argc, char **argv){ sqlite3_stmt *pStmt = 0; /* Statement to insert testcase into dataDb */ const char *zDataOut = 0; /* Write compacted data to this output file */ int nHeader = 0; /* Bytes of header comment text on input file */ + int oomFlag = 0; /* --oom */ + int oomCnt = 0; /* Counter for the OOM loop */ + char zErrBuf[200]; /* Space for the error message */ + const char *zFailCode; /* Value of the TEST_FAILURE environment var */ + zFailCode = getenv("TEST_FAILURE"); g.zArgv0 = argv[0]; for(i=1; i=argc-1 ) abendError("missing argument on %s", argv[i]); pageSize = integerValue(argv[++i]); @@ -480,6 +529,13 @@ int main(int argc, char **argv){ rc = sqlite3_config(SQLITE_CONFIG_HEAP, pHeap, nHeap, mnHeap); if( rc ) abendError("heap configuration failed: %d\n", rc); } + if( oomFlag ){ + sqlite3_config(SQLITE_CONFIG_GETMALLOC, &g.sOrigMem); + g.sOomMem = g.sOrigMem; + g.sOomMem.xMalloc = oomMalloc; + g.sOomMem.xRealloc = oomRealloc; + sqlite3_config(SQLITE_CONFIG_MALLOC, &g.sOomMem); + } if( nLook>0 ){ sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 0, 0); if( szLook>0 ){ @@ -557,45 +613,15 @@ int main(int argc, char **argv){ zIn[iNext] = cSaved; continue; } - rc = sqlite3_open_v2( - "main.db", &db, - SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY, - 0); - if( rc!=SQLITE_OK ){ - abendError("Unable to open the in-memory database"); - } - if( pLook ){ - rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, pLook, szLook, nLook); - if( rc!=SQLITE_OK ) abendError("lookaside configuration filed: %d", rc); - } - if( zInitDb ){ - sqlite3_backup *pBackup; - pBackup = sqlite3_backup_init(db, "main", dbInit, "main"); - rc = sqlite3_backup_step(pBackup, -1); - if( rc!=SQLITE_DONE ){ - abendError("attempt to initialize the in-memory database failed (rc=%d)", - rc); - } - sqlite3_backup_finish(pBackup); - } -#ifndef SQLITE_OMIT_TRACE - if( verboseFlag ) sqlite3_trace(db, traceCallback, 0); -#endif - sqlite3_create_function(db, "eval", 1, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0); - sqlite3_create_function(db, "eval", 2, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0); - sqlite3_limit(db, SQLITE_LIMIT_LENGTH, 1000000); - if( zEncoding ) sqlexec(db, "PRAGMA encoding=%s", zEncoding); - if( pageSize ) sqlexec(db, "PRAGMA pagesize=%d", pageSize); - if( doAutovac ) sqlexec(db, "PRAGMA auto_vacuum=FULL"); zSql = &zIn[i]; if( verboseFlag ){ printf("INPUT (offset: %d, size: %d): [%s]\n", i, (int)strlen(&zIn[i]), &zIn[i]); }else if( multiTest && !quietFlag ){ - int pct = 10*iNext/nIn; + int pct = oomFlag ? 100*iNext/nIn : ((10*iNext)/nIn)*10; if( pct!=lastPct ){ if( lastPct<0 ) printf("fuzz test:"); - printf(" %d%%", pct*10); + printf(" %d%%", pct); fflush(stdout); lastPct = pct; } @@ -611,8 +637,84 @@ int main(int argc, char **argv){ zSql = zToFree = sqlite3_mprintf("SELECT strftime(%s);", zSql); break; } - zErrMsg = 0; - rc = sqlite3_exec(db, zSql, verboseFlag ? execCallback : execNoop, 0, &zErrMsg); + if( oomFlag ){ + oomCnt = g.iOomCntdown = 1; + g.nOomFault = 0; + g.bOomOnce = 1; + if( verboseFlag ) printf("Once.%d\n", oomCnt); + }else{ + oomCnt = 0; + } + do{ + rc = sqlite3_open_v2( + "main.db", &db, + SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY, + 0); + if( rc!=SQLITE_OK ){ + abendError("Unable to open the in-memory database"); + } + if( pLook ){ + rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, pLook, szLook, nLook); + if( rc!=SQLITE_OK ) abendError("lookaside configuration filed: %d", rc); + } + if( zInitDb ){ + sqlite3_backup *pBackup; + pBackup = sqlite3_backup_init(db, "main", dbInit, "main"); + rc = sqlite3_backup_step(pBackup, -1); + if( rc!=SQLITE_DONE ){ + abendError("attempt to initialize the in-memory database failed (rc=%d)", + rc); + } + sqlite3_backup_finish(pBackup); + } + #ifndef SQLITE_OMIT_TRACE + if( verboseFlag ) sqlite3_trace(db, traceCallback, 0); + #endif + sqlite3_create_function(db, "eval", 1, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0); + sqlite3_create_function(db, "eval", 2, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0); + sqlite3_limit(db, SQLITE_LIMIT_LENGTH, 1000000); + if( zEncoding ) sqlexec(db, "PRAGMA encoding=%s", zEncoding); + if( pageSize ) sqlexec(db, "PRAGMA pagesize=%d", pageSize); + if( doAutovac ) sqlexec(db, "PRAGMA auto_vacuum=FULL"); + g.bOomEnable = 1; + if( verboseFlag ){ + zErrMsg = 0; + rc = sqlite3_exec(db, zSql, execCallback, 0, &zErrMsg); + if( zErrMsg ){ + sqlite3_snprintf(sizeof(zErrBuf),zErrBuf,"%z", zErrMsg); + zErrMsg = 0; + } + }else { + rc = sqlite3_exec(db, zSql, execNoop, 0, 0); + } + g.bOomEnable = 0; + rc = sqlite3_close(db); + if( rc ){ + abendError("sqlite3_close() failed with rc=%d", rc); + } + if( sqlite3_memory_used()>0 ){ + abendError("memory in use after close: %lld bytes", sqlite3_memory_used()); + } + if( oomFlag ){ + if( g.nOomFault==0 || oomCnt>2000 ){ + if( g.bOomOnce ){ + oomCnt = g.iOomCntdown = 1; + g.bOomOnce = 0; + }else{ + oomCnt = 0; + } + }else{ + g.iOomCntdown = ++oomCnt; + g.nOomFault = 0; + } + if( oomCnt ){ + if( verboseFlag ){ + printf("%s.%d\n", g.bOomOnce ? "Once" : "Multi", oomCnt); + } + nTest++; + } + } + }while( oomCnt>0 ); if( zToFree ){ sqlite3_free(zToFree); zToFree = 0; @@ -621,29 +723,18 @@ int main(int argc, char **argv){ if( verboseFlag ){ printf("RESULT-CODE: %d\n", rc); if( zErrMsg ){ - printf("ERROR-MSG: [%s]\n", zErrMsg); + printf("ERROR-MSG: [%s]\n", zErrBuf); } } - sqlite3_free(zErrMsg); - rc = sqlite3_close(db); - if( rc ){ - abendError("sqlite3_close() failed with rc=%d", rc); - } - if( sqlite3_memory_used()>0 ){ - abendError("memory in use after close: %lld bytes", sqlite3_memory_used()); - } - if( nTest==1 ){ - /* Simulate an error if the TEST_FAILURE environment variable is "5" */ - char *zFailCode = getenv("TEST_FAILURE"); - if( zFailCode ){ - if( zFailCode[0]=='5' && zFailCode[1]==0 ){ - abendError("simulated failure"); - }else if( zFailCode[0]!=0 ){ - /* If TEST_FAILURE is something other than 5, just exit the test - ** early */ - printf("\nExit early due to TEST_FAILURE being set"); - break; - } + /* Simulate an error if the TEST_FAILURE environment variable is "5" */ + if( zFailCode ){ + if( zFailCode[0]=='5' && zFailCode[1]==0 ){ + abendError("simulated failure"); + }else if( zFailCode[0]!=0 ){ + /* If TEST_FAILURE is something other than 5, just exit the test + ** early */ + printf("\nExit early due to TEST_FAILURE being set"); + break; } } }