SQLite

Check-in [119d6ef847]
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
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 119d6ef8478ea6ab07dfd0e974d2f5a8dcfce87e
User & Date: drh 2016-11-11 16:33:47.638
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: 46e0016207 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: 119d6ef847 user: drh tags: trunk)
15:49
Handle some obscure "row value misused" cases that could cause segfaults or assertion failures. (check-in: fba5fddb1c user: dan tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to main.mk.
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
	./srcck1 sqlite3.c

fuzzershell$(EXE):	$(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h
	$(TCCX) -o fuzzershell$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
	  $(FUZZERSHELL_OPT) $(TOP)/tool/fuzzershell.c sqlite3.c \
	  $(TLIBS) $(THREADLIB)

fuzzcheck$(EXE):	$(TOP)/test/fuzzcheck.c sqlite3.c sqlite3.h
	$(TCCX) -o fuzzcheck$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
		-DSQLITE_ENABLE_MEMSYS5 $(FUZZCHECK_OPT) \
		$(TOP)/test/fuzzcheck.c sqlite3.c $(TLIBS) $(THREADLIB)

mptester$(EXE):	sqlite3.c $(TOP)/mptest/mptest.c
	$(TCCX) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \
		$(TLIBS) $(THREADLIB)

MPTEST1=./mptester$(EXE) mptest1.db $(TOP)/mptest/crash01.test --repeat 20
MPTEST2=./mptester$(EXE) mptest2.db $(TOP)/mptest/multiwrite01.test --repeat 20







|

|
|







507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
	./srcck1 sqlite3.c

fuzzershell$(EXE):	$(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h
	$(TCCX) -o fuzzershell$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
	  $(FUZZERSHELL_OPT) $(TOP)/tool/fuzzershell.c sqlite3.c \
	  $(TLIBS) $(THREADLIB)

fuzzcheck$(EXE):	$(TOP)/test/fuzzcheck.c sqlite3.c sqlite3.h $(TOP)/test/ossfuzz.c
	$(TCCX) -o fuzzcheck$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
		-DSQLITE_ENABLE_MEMSYS5 $(FUZZCHECK_OPT) -DSQLITE_OSS_FUZZ \
		$(TOP)/test/fuzzcheck.c $(TOP)/test/ossfuzz.c sqlite3.c $(TLIBS) $(THREADLIB)

mptester$(EXE):	sqlite3.c $(TOP)/mptest/mptest.c
	$(TCCX) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \
		$(TLIBS) $(THREADLIB)

MPTEST1=./mptester$(EXE) mptest1.db $(TOP)/mptest/crash01.test --repeat 20
MPTEST2=./mptester$(EXE) mptest2.db $(TOP)/mptest/multiwrite01.test --repeat 20
Changes to test/fuzzcheck.c.
76
77
78
79
80
81
82





83
84
85
86
87
88
89


#ifdef __unix__
# include <signal.h>
# include <unistd.h>
#endif






/*
** Files in the virtual file system.
*/
typedef struct VFile VFile;
struct VFile {
  char *zFilename;        /* Filename.  NULL for delete-on-close. From malloc() */
  int sz;                 /* Size of the file in bytes */







>
>
>
>
>







76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94


#ifdef __unix__
# include <signal.h>
# include <unistd.h>
#endif

#ifdef SQLITE_OSS_FUZZ
# include <stddef.h>
# include <stdint.h>
#endif

/*
** Files in the virtual file system.
*/
typedef struct VFile VFile;
struct VFile {
  char *zFilename;        /* Filename.  NULL for delete-on-close. From malloc() */
  int sz;                 /* Size of the file in bytes */
790
791
792
793
794
795
796

797
798
799
800
801
802
803
"  -q|--quiet           Reduced output\n"
"  --limit-mem N        Limit memory used by test SQLite instance to N bytes\n"
"  --limit-vdbe         Panic if any test runs for more than 100,000 cycles\n"
"  --load-sql ARGS...   Load SQL scripts fro files into SOURCE-DB\n"
"  --load-db ARGS...    Load template databases from files into SOURCE_DB\n"
"  -m TEXT              Add a description to the database\n"
"  --native-vfs         Use the native VFS for initially empty database files\n"

"  --rebuild            Rebuild and vacuum the database file\n"
"  --result-trace       Show the results of each SQL command\n"
"  --sqlid N            Use only SQL where sqlid=N\n"
"  --timeout N          Abort if any single test needs more than N seconds\n"
"  -v|--verbose         Increased output.  Repeat for more output.\n"
  );
}







>







795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
"  -q|--quiet           Reduced output\n"
"  --limit-mem N        Limit memory used by test SQLite instance to N bytes\n"
"  --limit-vdbe         Panic if any test runs for more than 100,000 cycles\n"
"  --load-sql ARGS...   Load SQL scripts fro files into SOURCE-DB\n"
"  --load-db ARGS...    Load template databases from files into SOURCE_DB\n"
"  -m TEXT              Add a description to the database\n"
"  --native-vfs         Use the native VFS for initially empty database files\n"
"  --oss-fuzz           Enable OSS-FUZZ testing\n"
"  --rebuild            Rebuild and vacuum the database file\n"
"  --result-trace       Show the results of each SQL command\n"
"  --sqlid N            Use only SQL where sqlid=N\n"
"  --timeout N          Abort if any single test needs more than N seconds\n"
"  -v|--verbose         Increased output.  Repeat for more output.\n"
  );
}
831
832
833
834
835
836
837

838
839
840
841
842
843
844
  int cellSzCkFlag = 0;        /* --cell-size-check */
  int sqlFuzz = 0;             /* True for SQL fuzz testing. False for DB fuzz */
  int iTimeout = 120;          /* Default 120-second timeout */
  int nMem = 0;                /* Memory limit */
  char *zExpDb = 0;            /* Write Databases to files in this directory */
  char *zExpSql = 0;           /* Write SQL to files in this directory */
  void *pHeap = 0;             /* Heap for use by SQLite */


  iBegin = timeOfDay();
#ifdef __unix__
  signal(SIGALRM, timeoutHandler);
#endif
  g.zArgv0 = argv[0];
  zFailCode = getenv("TEST_FAILURE");







>







837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
  int cellSzCkFlag = 0;        /* --cell-size-check */
  int sqlFuzz = 0;             /* True for SQL fuzz testing. False for DB fuzz */
  int iTimeout = 120;          /* Default 120-second timeout */
  int nMem = 0;                /* Memory limit */
  char *zExpDb = 0;            /* Write Databases to files in this directory */
  char *zExpSql = 0;           /* Write SQL to files in this directory */
  void *pHeap = 0;             /* Heap for use by SQLite */
  int ossFuzz = 0;             /* enable OSS-FUZZ testing */

  iBegin = timeOfDay();
#ifdef __unix__
  signal(SIGALRM, timeoutHandler);
#endif
  g.zArgv0 = argv[0];
  zFailCode = getenv("TEST_FAILURE");
890
891
892
893
894
895
896



897
898
899
900
901
902
903
      }else
      if( strcmp(z,"m")==0 ){
        if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
        zMsg = argv[++i];
      }else
      if( strcmp(z,"native-vfs")==0 ){
        nativeFlag = 1;



      }else
      if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){
        quietFlag = 1;
        verboseFlag = 0;
      }else
      if( strcmp(z,"rebuild")==0 ){
        rebuildFlag = 1;







>
>
>







897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
      }else
      if( strcmp(z,"m")==0 ){
        if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
        zMsg = argv[++i];
      }else
      if( strcmp(z,"native-vfs")==0 ){
        nativeFlag = 1;
      }else
      if( strcmp(z,"oss-fuzz")==0 ){
        ossFuzz = 1;
      }else
      if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){
        quietFlag = 1;
        verboseFlag = 0;
      }else
      if( strcmp(z,"rebuild")==0 ){
        rebuildFlag = 1;
1119
1120
1121
1122
1123
1124
1125








1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144

1145
1146
1147
1148
1149
1150
1151
          if( amt!=prevAmt ){
            printf(" %d%%", amt*10);
            fflush(stdout);
            prevAmt = amt;
          }
        }
        createVFile("main.db", pDb->sz, pDb->a);








        openFlags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE;
        if( nativeFlag && pDb->sz==0 ){
          openFlags |= SQLITE_OPEN_MEMORY;
          zVfs = 0;
        }
        rc = sqlite3_open_v2("main.db", &db, openFlags, zVfs);
        if( rc ) fatalError("cannot open inmem database");
        if( cellSzCkFlag ) runSql(db, "PRAGMA cell_size_check=ON", runFlags);
        setAlarm(iTimeout);
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
        if( sqlFuzz || vdbeLimitFlag ){
          sqlite3_progress_handler(db, 100000, progressHandler, &vdbeLimitFlag);
        }
#endif
        do{
          runSql(db, (char*)pSql->a, runFlags);
        }while( timeoutTest );
        setAlarm(0);
        sqlite3_close(db);

        if( sqlite3_memory_used()>0 ) fatalError("memory leak");
        reformatVfs();
        nTest++;
        g.zTestName[0] = 0;

        /* Simulate an error if the TEST_FAILURE environment variable is "5".
        ** This is used to verify that automated test script really do spot







>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
|
|

|
|
|

|
|
|
|
|
>







1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
          if( amt!=prevAmt ){
            printf(" %d%%", amt*10);
            fflush(stdout);
            prevAmt = amt;
          }
        }
        createVFile("main.db", pDb->sz, pDb->a);
        if( ossFuzz ){
#ifndef SQLITE_OSS_FUZZ
          fatalError("--oss-fuzz not supported: recompile with -DSQLITE_OSS_FUZZ");
#else
          extern int LLVMFuzzerTestOneInput(const uint8_t*, size_t);
          LLVMFuzzerTestOneInput((const uint8_t*)pSql->a, (size_t)pSql->sz);
#endif
        }else{
          openFlags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE;
          if( nativeFlag && pDb->sz==0 ){
            openFlags |= SQLITE_OPEN_MEMORY;
            zVfs = 0;
          }
          rc = sqlite3_open_v2("main.db", &db, openFlags, zVfs);
          if( rc ) fatalError("cannot open inmem database");
          if( cellSzCkFlag ) runSql(db, "PRAGMA cell_size_check=ON", runFlags);
          setAlarm(iTimeout);
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
          if( sqlFuzz || vdbeLimitFlag ){
            sqlite3_progress_handler(db, 100000, progressHandler, &vdbeLimitFlag);
          }
#endif
          do{
            runSql(db, (char*)pSql->a, runFlags);
          }while( timeoutTest );
          setAlarm(0);
          sqlite3_close(db);
        }
        if( sqlite3_memory_used()>0 ) fatalError("memory leak");
        reformatVfs();
        nTest++;
        g.zTestName[0] = 0;

        /* Simulate an error if the TEST_FAILURE environment variable is "5".
        ** This is used to verify that automated test script really do spot
Added test/ossfuzz.c.
































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
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
73
74
75
76
77
78
79
80
/*
** This module interfaces SQLite to the Google OSS-Fuzz, fuzzer as a service.
** (https://github.com/google/oss-fuzz)
*/
#include <stddef.h>
#include <stdint.h>
#include "sqlite3.h"

/*
** Progress handler callback
*/
static int progress_handler(void *pReturn) {
  return *(int*)pReturn;
}

/*
** Callback for sqlite3_exec().
*/
static int exec_handler(void *pCnt, int argc, char **argv, char **namev){
  int i;
  for(i=0; i<argc; i++) sqlite3_free(sqlite3_mprintf("%s", argv[i]));
  return ((*(int*)pCnt)--)<=0;
}

/*
** Main entry point.  The fuzzer invokes this function with each
** fuzzed input.
*/
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
  int progressArg = 0;     /* 1 causes progress handler abort */
  int execCnt = 0;         /* Abort row callback when count reaches zero */
  char *zErrMsg = 0;       /* Error message returned by sqlite_exec() */
  sqlite3 *db;             /* The database connection */
  uint8_t uSelector;       /* First byte of input data[] */
  int rc;                  /* Return code from various interfaces */
  char *zSql;              /* Zero-terminated copy of data[] */

  if( size<3 ) return 0;   /* Early out if unsufficient data */

  /* Extract the selector byte from the beginning of the input.  But only
  ** do this if the second byte is a \n.  If the second byte is not \n,
  ** then use a default selector */
  if( data[1]=='\n' ){
    uSelector = data[0];  data += 2; size -= 2;
  }else{
    uSelector = 0xfd;
  }

  /* Open the database connection.  Only use an in-memory database. */
  rc = sqlite3_open_v2("fuzz.db", &db,
           SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY, 0);
  if( rc ) return 0;

  /* Bit 0 of the selector enables progress callbacks.  Bit 1 is the
  ** return code from progress callbacks */
  if( uSelector & 1 ){
    sqlite3_progress_handler(db, 4, progress_handler, (void*)&progressArg);
  }
  uSelector >>= 1;
  progressArg = uSelector & 1;  uSelector >>= 1;

  /* Bit 2 of the selector enables foreign key constraints */
  sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_FKEY, uSelector&1, &rc);
  uSelector >>= 1;

  /* Remaining bits of the selector determine a limit on the number of
  ** output rows */
  execCnt = uSelector + 1;

  /* Run the SQL.  The sqlite_exec() interface expects a zero-terminated
  ** string, so make a copy. */
  zSql = sqlite3_mprintf("%.*s", (int)size, data);
  sqlite3_exec(db, zSql, exec_handler, (void*)&execCnt, &zErrMsg);

  /* Cleanup and return */
  sqlite3_free(zErrMsg);
  sqlite3_free(zSql);
  sqlite3_close(db);
  return 0;
}