drh | 65da285 | 2018-10-27 00:47:33 +0000 | [diff] [blame] | 1 | /* |
| 2 | ** 2018-10-26 |
| 3 | ** |
| 4 | ** The author disclaims copyright to this source code. In place of |
| 5 | ** a legal notice, here is a blessing: |
| 6 | ** |
| 7 | ** May you do good and not evil. |
| 8 | ** May you find forgiveness for yourself and forgive others. |
| 9 | ** May you share freely, never taking more than you give. |
| 10 | ** |
| 11 | ************************************************************************* |
| 12 | ** |
| 13 | ** This program is designed for fuzz-testing SQLite database files using |
| 14 | ** the -fsanitize=fuzzer option of clang. |
| 15 | ** |
| 16 | ** The -fsanitize=fuzzer option causes a main() to be inserted automatically. |
| 17 | ** That main() invokes LLVMFuzzerTestOneInput(D,S) to be invoked repeatedly. |
| 18 | ** Each D is a fuzzed database file. The code in this file runs various |
| 19 | ** SQL statements against that database, trying to provoke a failure. |
| 20 | ** |
| 21 | ** For best results the seed database files should have these tables: |
| 22 | ** |
| 23 | ** Table "t1" with columns "a" and "b" |
| 24 | ** Tables "t2" and "t3 with the same number of compatible columns |
| 25 | ** "t3" should have a column names "x" |
| 26 | ** Table "t4" with a column "x" that is compatible with t3.x. |
| 27 | ** |
| 28 | ** Any of these tables can be virtual tables, for example FTS or RTree tables. |
| 29 | ** |
| 30 | ** To run this test: |
| 31 | ** |
| 32 | ** mkdir dir |
| 33 | ** cp dbfuzz2-seed*.db dir |
| 34 | ** clang-6.0 -I. -g -O1 -fsanitize=fuzzer \ |
| 35 | ** -DTHREADSAFE=0 -DSQLITE_ENABLE_DESERIALIZE \ |
| 36 | ** -DSQLITE_ENABLE_DBSTAT_VTAB dbfuzz2.c sqlite3.c -ldl |
| 37 | ** ./a.out dir |
| 38 | */ |
| 39 | #include <assert.h> |
| 40 | #include <stdio.h> |
| 41 | #include <stdlib.h> |
| 42 | #include <string.h> |
| 43 | #include <stdarg.h> |
| 44 | #include <ctype.h> |
| 45 | #include <stdint.h> |
| 46 | #include "sqlite3.h" |
| 47 | |
| 48 | /* |
| 49 | ** This is the is the SQL that is run against the database. |
| 50 | */ |
| 51 | static const char *azSql[] = { |
| 52 | "PRAGMA integrity_check;", |
| 53 | "SELECT * FROM sqlite_master;", |
| 54 | "SELECT sum(length(name)) FROM dbstat;", |
| 55 | "UPDATE t1 SET b=a, a=b WHERE a<b;", |
drh | d811d84 | 2018-10-27 21:06:44 +0000 | [diff] [blame] | 56 | "ALTER TABLE t1 RENAME TO alkjalkjdfiiiwuer987lkjwer82mx97sf98788s9789s;", |
drh | 65da285 | 2018-10-27 00:47:33 +0000 | [diff] [blame] | 57 | "INSERT INTO t3 SELECT * FROM t2;", |
| 58 | "DELETE FROM t3 WHERE x IN (SELECT x FROM t4);", |
drh | d811d84 | 2018-10-27 21:06:44 +0000 | [diff] [blame] | 59 | "REINDEX;", |
drh | 65da285 | 2018-10-27 00:47:33 +0000 | [diff] [blame] | 60 | "DROP TABLE t3;", |
| 61 | "VACUUM;", |
| 62 | }; |
| 63 | |
drh | d811d84 | 2018-10-27 21:06:44 +0000 | [diff] [blame] | 64 | /* Output verbosity level. 0 means complete silence */ |
| 65 | int eVerbosity = 0; |
| 66 | |
| 67 | /* libFuzzer invokes this routine with fuzzed database files (in aData). |
| 68 | ** This routine run SQLite against the malformed database to see if it |
| 69 | ** can provoke a failure or malfunction. |
| 70 | */ |
drh | 65da285 | 2018-10-27 00:47:33 +0000 | [diff] [blame] | 71 | int LLVMFuzzerTestOneInput(const uint8_t *aData, size_t nByte){ |
| 72 | unsigned char *a; |
| 73 | sqlite3 *db; |
| 74 | int rc; |
| 75 | int i; |
| 76 | |
drh | d811d84 | 2018-10-27 21:06:44 +0000 | [diff] [blame] | 77 | if( eVerbosity>=1 ){ |
| 78 | printf("************** nByte=%d ***************\n", (int)nByte); |
| 79 | fflush(stdout); |
| 80 | } |
drh | ad9bfa5 | 2018-10-30 15:20:35 +0000 | [diff] [blame] | 81 | rc = sqlite3_open(0, &db); |
drh | 65da285 | 2018-10-27 00:47:33 +0000 | [diff] [blame] | 82 | if( rc ) return 1; |
drh | ad9bfa5 | 2018-10-30 15:20:35 +0000 | [diff] [blame] | 83 | a = sqlite3_malloc64(nByte+1); |
drh | 65da285 | 2018-10-27 00:47:33 +0000 | [diff] [blame] | 84 | if( a==0 ) return 1; |
| 85 | memcpy(a, aData, nByte); |
| 86 | sqlite3_deserialize(db, "main", a, nByte, nByte, |
| 87 | SQLITE_DESERIALIZE_RESIZEABLE | |
| 88 | SQLITE_DESERIALIZE_FREEONCLOSE); |
| 89 | for(i=0; i<sizeof(azSql)/sizeof(azSql[0]); i++){ |
drh | d811d84 | 2018-10-27 21:06:44 +0000 | [diff] [blame] | 90 | if( eVerbosity>=1 ){ |
| 91 | printf("%s\n", azSql[i]); |
| 92 | fflush(stdout); |
| 93 | } |
drh | 65da285 | 2018-10-27 00:47:33 +0000 | [diff] [blame] | 94 | sqlite3_exec(db, azSql[i], 0, 0, 0); |
| 95 | } |
drh | ad9bfa5 | 2018-10-30 15:20:35 +0000 | [diff] [blame] | 96 | rc = sqlite3_close(db); |
| 97 | if( rc!=SQLITE_OK ){ |
| 98 | fprintf(stdout, "sqlite3_close() returns %d\n", rc); |
| 99 | } |
drh | d811d84 | 2018-10-27 21:06:44 +0000 | [diff] [blame] | 100 | if( sqlite3_memory_used()!=0 ){ |
drh | ad9bfa5 | 2018-10-30 15:20:35 +0000 | [diff] [blame] | 101 | int nAlloc = 0; |
| 102 | int nNotUsed = 0; |
| 103 | sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &nAlloc, &nNotUsed, 0); |
| 104 | fprintf(stderr,"Memory leak: %lld bytes in %d allocations\n", |
| 105 | sqlite3_memory_used(), nAlloc); |
drh | d811d84 | 2018-10-27 21:06:44 +0000 | [diff] [blame] | 106 | exit(1); |
| 107 | } |
| 108 | return 0; |
| 109 | } |
| 110 | |
| 111 | /* libFuzzer invokes this routine once when the executable starts, to |
| 112 | ** process the command-line arguments. |
| 113 | */ |
| 114 | int LLVMFuzzerInitialize(int *pArgc, char ***pArgv){ |
| 115 | int i, j; |
| 116 | int argc = *pArgc; |
| 117 | char **newArgv; |
| 118 | char **argv = *pArgv; |
| 119 | newArgv = malloc( sizeof(char*)*(argc+1) ); |
| 120 | if( newArgv==0 ) return 0; |
| 121 | newArgv[0] = argv[0]; |
| 122 | for(i=j=1; i<argc; i++){ |
| 123 | char *z = argv[i]; |
| 124 | if( z[0]=='-' ){ |
| 125 | z++; |
| 126 | if( z[0]=='-' ) z++; |
| 127 | if( strcmp(z,"v")==0 ){ |
| 128 | eVerbosity++; |
| 129 | continue; |
| 130 | } |
| 131 | } |
| 132 | newArgv[j++] = argv[i]; |
| 133 | } |
| 134 | newArgv[j] = 0; |
| 135 | *pArgv = newArgv; |
| 136 | *pArgc = j; |
drh | 65da285 | 2018-10-27 00:47:33 +0000 | [diff] [blame] | 137 | return 0; |
| 138 | } |