/ Check-in [119d6ef8]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add the test/ossfuzz.c interface adaptor for OSS-FUZZ. Make previsions for testing the adaptor using fuzzcheck.c.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 119d6ef8478ea6ab07dfd0e974d2f5a8dcfce87e
User & Date: drh 2016-11-11 16:33:47
Context
2016-11-11
17:08
Fix a problem with switching from wal to rollback mode when SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE is configured. check-in: 46e00162 user: dan tags: trunk
16:33
Add the test/ossfuzz.c interface adaptor for OSS-FUZZ. Make previsions for testing the adaptor using fuzzcheck.c. check-in: 119d6ef8 user: drh tags: trunk
15:49
Handle some obscure "row value misused" cases that could cause segfaults or assertion failures. check-in: fba5fddb user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to main.mk.

   507    507   	./srcck1 sqlite3.c
   508    508   
   509    509   fuzzershell$(EXE):	$(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h
   510    510   	$(TCCX) -o fuzzershell$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
   511    511   	  $(FUZZERSHELL_OPT) $(TOP)/tool/fuzzershell.c sqlite3.c \
   512    512   	  $(TLIBS) $(THREADLIB)
   513    513   
   514         -fuzzcheck$(EXE):	$(TOP)/test/fuzzcheck.c sqlite3.c sqlite3.h
          514  +fuzzcheck$(EXE):	$(TOP)/test/fuzzcheck.c sqlite3.c sqlite3.h $(TOP)/test/ossfuzz.c
   515    515   	$(TCCX) -o fuzzcheck$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
   516         -		-DSQLITE_ENABLE_MEMSYS5 $(FUZZCHECK_OPT) \
   517         -		$(TOP)/test/fuzzcheck.c sqlite3.c $(TLIBS) $(THREADLIB)
          516  +		-DSQLITE_ENABLE_MEMSYS5 $(FUZZCHECK_OPT) -DSQLITE_OSS_FUZZ \
          517  +		$(TOP)/test/fuzzcheck.c $(TOP)/test/ossfuzz.c sqlite3.c $(TLIBS) $(THREADLIB)
   518    518   
   519    519   mptester$(EXE):	sqlite3.c $(TOP)/mptest/mptest.c
   520    520   	$(TCCX) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \
   521    521   		$(TLIBS) $(THREADLIB)
   522    522   
   523    523   MPTEST1=./mptester$(EXE) mptest1.db $(TOP)/mptest/crash01.test --repeat 20
   524    524   MPTEST2=./mptester$(EXE) mptest2.db $(TOP)/mptest/multiwrite01.test --repeat 20

Changes to test/fuzzcheck.c.

    76     76   
    77     77   
    78     78   #ifdef __unix__
    79     79   # include <signal.h>
    80     80   # include <unistd.h>
    81     81   #endif
    82     82   
           83  +#ifdef SQLITE_OSS_FUZZ
           84  +# include <stddef.h>
           85  +# include <stdint.h>
           86  +#endif
           87  +
    83     88   /*
    84     89   ** Files in the virtual file system.
    85     90   */
    86     91   typedef struct VFile VFile;
    87     92   struct VFile {
    88     93     char *zFilename;        /* Filename.  NULL for delete-on-close. From malloc() */
    89     94     int sz;                 /* Size of the file in bytes */
................................................................................
   790    795   "  -q|--quiet           Reduced output\n"
   791    796   "  --limit-mem N        Limit memory used by test SQLite instance to N bytes\n"
   792    797   "  --limit-vdbe         Panic if any test runs for more than 100,000 cycles\n"
   793    798   "  --load-sql ARGS...   Load SQL scripts fro files into SOURCE-DB\n"
   794    799   "  --load-db ARGS...    Load template databases from files into SOURCE_DB\n"
   795    800   "  -m TEXT              Add a description to the database\n"
   796    801   "  --native-vfs         Use the native VFS for initially empty database files\n"
          802  +"  --oss-fuzz           Enable OSS-FUZZ testing\n"
   797    803   "  --rebuild            Rebuild and vacuum the database file\n"
   798    804   "  --result-trace       Show the results of each SQL command\n"
   799    805   "  --sqlid N            Use only SQL where sqlid=N\n"
   800    806   "  --timeout N          Abort if any single test needs more than N seconds\n"
   801    807   "  -v|--verbose         Increased output.  Repeat for more output.\n"
   802    808     );
   803    809   }
................................................................................
   831    837     int cellSzCkFlag = 0;        /* --cell-size-check */
   832    838     int sqlFuzz = 0;             /* True for SQL fuzz testing. False for DB fuzz */
   833    839     int iTimeout = 120;          /* Default 120-second timeout */
   834    840     int nMem = 0;                /* Memory limit */
   835    841     char *zExpDb = 0;            /* Write Databases to files in this directory */
   836    842     char *zExpSql = 0;           /* Write SQL to files in this directory */
   837    843     void *pHeap = 0;             /* Heap for use by SQLite */
          844  +  int ossFuzz = 0;             /* enable OSS-FUZZ testing */
   838    845   
   839    846     iBegin = timeOfDay();
   840    847   #ifdef __unix__
   841    848     signal(SIGALRM, timeoutHandler);
   842    849   #endif
   843    850     g.zArgv0 = argv[0];
   844    851     zFailCode = getenv("TEST_FAILURE");
................................................................................
   890    897         }else
   891    898         if( strcmp(z,"m")==0 ){
   892    899           if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
   893    900           zMsg = argv[++i];
   894    901         }else
   895    902         if( strcmp(z,"native-vfs")==0 ){
   896    903           nativeFlag = 1;
          904  +      }else
          905  +      if( strcmp(z,"oss-fuzz")==0 ){
          906  +        ossFuzz = 1;
   897    907         }else
   898    908         if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){
   899    909           quietFlag = 1;
   900    910           verboseFlag = 0;
   901    911         }else
   902    912         if( strcmp(z,"rebuild")==0 ){
   903    913           rebuildFlag = 1;
................................................................................
  1119   1129             if( amt!=prevAmt ){
  1120   1130               printf(" %d%%", amt*10);
  1121   1131               fflush(stdout);
  1122   1132               prevAmt = amt;
  1123   1133             }
  1124   1134           }
  1125   1135           createVFile("main.db", pDb->sz, pDb->a);
  1126         -        openFlags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE;
  1127         -        if( nativeFlag && pDb->sz==0 ){
  1128         -          openFlags |= SQLITE_OPEN_MEMORY;
  1129         -          zVfs = 0;
  1130         -        }
  1131         -        rc = sqlite3_open_v2("main.db", &db, openFlags, zVfs);
  1132         -        if( rc ) fatalError("cannot open inmem database");
  1133         -        if( cellSzCkFlag ) runSql(db, "PRAGMA cell_size_check=ON", runFlags);
  1134         -        setAlarm(iTimeout);
         1136  +        if( ossFuzz ){
         1137  +#ifndef SQLITE_OSS_FUZZ
         1138  +          fatalError("--oss-fuzz not supported: recompile with -DSQLITE_OSS_FUZZ");
         1139  +#else
         1140  +          extern int LLVMFuzzerTestOneInput(const uint8_t*, size_t);
         1141  +          LLVMFuzzerTestOneInput((const uint8_t*)pSql->a, (size_t)pSql->sz);
         1142  +#endif
         1143  +        }else{
         1144  +          openFlags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE;
         1145  +          if( nativeFlag && pDb->sz==0 ){
         1146  +            openFlags |= SQLITE_OPEN_MEMORY;
         1147  +            zVfs = 0;
         1148  +          }
         1149  +          rc = sqlite3_open_v2("main.db", &db, openFlags, zVfs);
         1150  +          if( rc ) fatalError("cannot open inmem database");
         1151  +          if( cellSzCkFlag ) runSql(db, "PRAGMA cell_size_check=ON", runFlags);
         1152  +          setAlarm(iTimeout);
  1135   1153   #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  1136         -        if( sqlFuzz || vdbeLimitFlag ){
  1137         -          sqlite3_progress_handler(db, 100000, progressHandler, &vdbeLimitFlag);
  1138         -        }
         1154  +          if( sqlFuzz || vdbeLimitFlag ){
         1155  +            sqlite3_progress_handler(db, 100000, progressHandler, &vdbeLimitFlag);
         1156  +          }
  1139   1157   #endif
  1140         -        do{
  1141         -          runSql(db, (char*)pSql->a, runFlags);
  1142         -        }while( timeoutTest );
  1143         -        setAlarm(0);
  1144         -        sqlite3_close(db);
         1158  +          do{
         1159  +            runSql(db, (char*)pSql->a, runFlags);
         1160  +          }while( timeoutTest );
         1161  +          setAlarm(0);
         1162  +          sqlite3_close(db);
         1163  +        }
  1145   1164           if( sqlite3_memory_used()>0 ) fatalError("memory leak");
  1146   1165           reformatVfs();
  1147   1166           nTest++;
  1148   1167           g.zTestName[0] = 0;
  1149   1168   
  1150   1169           /* Simulate an error if the TEST_FAILURE environment variable is "5".
  1151   1170           ** This is used to verify that automated test script really do spot

Added test/ossfuzz.c.

            1  +/*
            2  +** This module interfaces SQLite to the Google OSS-Fuzz, fuzzer as a service.
            3  +** (https://github.com/google/oss-fuzz)
            4  +*/
            5  +#include <stddef.h>
            6  +#include <stdint.h>
            7  +#include "sqlite3.h"
            8  +
            9  +/*
           10  +** Progress handler callback
           11  +*/
           12  +static int progress_handler(void *pReturn) {
           13  +  return *(int*)pReturn;
           14  +}
           15  +
           16  +/*
           17  +** Callback for sqlite3_exec().
           18  +*/
           19  +static int exec_handler(void *pCnt, int argc, char **argv, char **namev){
           20  +  int i;
           21  +  for(i=0; i<argc; i++) sqlite3_free(sqlite3_mprintf("%s", argv[i]));
           22  +  return ((*(int*)pCnt)--)<=0;
           23  +}
           24  +
           25  +/*
           26  +** Main entry point.  The fuzzer invokes this function with each
           27  +** fuzzed input.
           28  +*/
           29  +int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
           30  +  int progressArg = 0;     /* 1 causes progress handler abort */
           31  +  int execCnt = 0;         /* Abort row callback when count reaches zero */
           32  +  char *zErrMsg = 0;       /* Error message returned by sqlite_exec() */
           33  +  sqlite3 *db;             /* The database connection */
           34  +  uint8_t uSelector;       /* First byte of input data[] */
           35  +  int rc;                  /* Return code from various interfaces */
           36  +  char *zSql;              /* Zero-terminated copy of data[] */
           37  +
           38  +  if( size<3 ) return 0;   /* Early out if unsufficient data */
           39  +
           40  +  /* Extract the selector byte from the beginning of the input.  But only
           41  +  ** do this if the second byte is a \n.  If the second byte is not \n,
           42  +  ** then use a default selector */
           43  +  if( data[1]=='\n' ){
           44  +    uSelector = data[0];  data += 2; size -= 2;
           45  +  }else{
           46  +    uSelector = 0xfd;
           47  +  }
           48  +
           49  +  /* Open the database connection.  Only use an in-memory database. */
           50  +  rc = sqlite3_open_v2("fuzz.db", &db,
           51  +           SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY, 0);
           52  +  if( rc ) return 0;
           53  +
           54  +  /* Bit 0 of the selector enables progress callbacks.  Bit 1 is the
           55  +  ** return code from progress callbacks */
           56  +  if( uSelector & 1 ){
           57  +    sqlite3_progress_handler(db, 4, progress_handler, (void*)&progressArg);
           58  +  }
           59  +  uSelector >>= 1;
           60  +  progressArg = uSelector & 1;  uSelector >>= 1;
           61  +
           62  +  /* Bit 2 of the selector enables foreign key constraints */
           63  +  sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_FKEY, uSelector&1, &rc);
           64  +  uSelector >>= 1;
           65  +
           66  +  /* Remaining bits of the selector determine a limit on the number of
           67  +  ** output rows */
           68  +  execCnt = uSelector + 1;
           69  +
           70  +  /* Run the SQL.  The sqlite_exec() interface expects a zero-terminated
           71  +  ** string, so make a copy. */
           72  +  zSql = sqlite3_mprintf("%.*s", (int)size, data);
           73  +  sqlite3_exec(db, zSql, exec_handler, (void*)&execCnt, &zErrMsg);
           74  +
           75  +  /* Cleanup and return */
           76  +  sqlite3_free(zErrMsg);
           77  +  sqlite3_free(zSql);
           78  +  sqlite3_close(db);
           79  +  return 0;
           80  +}