]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add the --oom option to fuzzershell.
authordrh <drh@noemail.net>
Fri, 24 Apr 2015 23:45:23 +0000 (23:45 +0000)
committerdrh <drh@noemail.net>
Fri, 24 Apr 2015 23:45:23 +0000 (23:45 +0000)
FossilOrigin-Name: 14a9e4a377bf2974f5db148c8f86e2c5ffdfa28d

manifest
manifest.uuid
tool/fuzzershell.c

index d8496c7409134472a236a79d3e47dd6b33caf39d..1418aef9a3747eb3b15c9d3065b3d6b4df7ce6cf 100644 (file)
--- 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
index f42387d8b96f916242e0fd4ebbc3694f54ec9986..18bce8061613b34da2dd14f53c0846d5b43a5ce2 100644 (file)
@@ -1 +1 @@
-dc88fe7e641c52d27fba8c753cee590db87388c5
\ No newline at end of file
+14a9e4a377bf2974f5db148c8f86e2c5ffdfa28d
\ No newline at end of file
index 51f1a636604e6816ce338767b47204d0a42b8662..5c0da82a4308ee3291697fa835d7e268538eb437 100644 (file)
 ** 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; i++){
     const char *z = argv[i];
@@ -431,6 +477,9 @@ int main(int argc, char **argv){
           abendError("unknown --mode: %s", z);
         }
       }else
+      if( strcmp(z,"oom")==0 ){
+        oomFlag = 1;
+      }else
       if( strcmp(z,"pagesize")==0 ){
         if( 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;
       }
     }
   }