blob: 67aa88cbb5460ca80055a29f26bbf36a63b0b81f [file] [log] [blame]
drh65da2852018-10-27 00:47:33 +00001/*
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>
drh7e85e902019-02-20 19:06:16 +000046#ifndef _WIN32
drh8ed07d12019-01-20 00:03:59 +000047#include <sys/time.h>
48#include <sys/resource.h>
drh7e85e902019-02-20 19:06:16 +000049#endif
drh65da2852018-10-27 00:47:33 +000050#include "sqlite3.h"
51
52/*
53** This is the is the SQL that is run against the database.
54*/
55static const char *azSql[] = {
56 "PRAGMA integrity_check;",
57 "SELECT * FROM sqlite_master;",
58 "SELECT sum(length(name)) FROM dbstat;",
59 "UPDATE t1 SET b=a, a=b WHERE a<b;",
drhd811d842018-10-27 21:06:44 +000060 "ALTER TABLE t1 RENAME TO alkjalkjdfiiiwuer987lkjwer82mx97sf98788s9789s;",
drh65da2852018-10-27 00:47:33 +000061 "INSERT INTO t3 SELECT * FROM t2;",
62 "DELETE FROM t3 WHERE x IN (SELECT x FROM t4);",
drhd811d842018-10-27 21:06:44 +000063 "REINDEX;",
drh65da2852018-10-27 00:47:33 +000064 "DROP TABLE t3;",
65 "VACUUM;",
66};
67
drhd811d842018-10-27 21:06:44 +000068/* Output verbosity level. 0 means complete silence */
69int eVerbosity = 0;
70
drh1972c8c2019-01-11 14:38:47 +000071/* True to activate PRAGMA vdbe_debug=on */
72static int bVdbeDebug = 0;
73
drh178edcd2019-01-22 16:11:31 +000074/* Maximum size of the in-memory database file */
75static sqlite3_int64 szMax = 104857600;
76
drha7908822019-02-04 19:50:44 +000077/***** Copy/paste from ext/misc/memtrace.c ***************************/
78/* The original memory allocation routines */
79static sqlite3_mem_methods memtraceBase;
80static FILE *memtraceOut;
81
82/* Methods that trace memory allocations */
83static void *memtraceMalloc(int n){
84 if( memtraceOut ){
85 fprintf(memtraceOut, "MEMTRACE: allocate %d bytes\n",
86 memtraceBase.xRoundup(n));
87 }
88 return memtraceBase.xMalloc(n);
89}
90static void memtraceFree(void *p){
91 if( p==0 ) return;
92 if( memtraceOut ){
93 fprintf(memtraceOut, "MEMTRACE: free %d bytes\n", memtraceBase.xSize(p));
94 }
95 memtraceBase.xFree(p);
96}
97static void *memtraceRealloc(void *p, int n){
98 if( p==0 ) return memtraceMalloc(n);
99 if( n==0 ){
100 memtraceFree(p);
101 return 0;
102 }
103 if( memtraceOut ){
104 fprintf(memtraceOut, "MEMTRACE: resize %d -> %d bytes\n",
105 memtraceBase.xSize(p), memtraceBase.xRoundup(n));
106 }
107 return memtraceBase.xRealloc(p, n);
108}
109static int memtraceSize(void *p){
110 return memtraceBase.xSize(p);
111}
112static int memtraceRoundup(int n){
113 return memtraceBase.xRoundup(n);
114}
115static int memtraceInit(void *p){
116 return memtraceBase.xInit(p);
117}
118static void memtraceShutdown(void *p){
119 memtraceBase.xShutdown(p);
120}
121
122/* The substitute memory allocator */
123static sqlite3_mem_methods ersaztMethods = {
124 memtraceMalloc,
125 memtraceFree,
126 memtraceRealloc,
127 memtraceSize,
128 memtraceRoundup,
129 memtraceInit,
130 memtraceShutdown
131};
132
133/* Begin tracing memory allocations to out. */
134int sqlite3MemTraceActivate(FILE *out){
135 int rc = SQLITE_OK;
136 if( memtraceBase.xMalloc==0 ){
137 rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memtraceBase);
138 if( rc==SQLITE_OK ){
139 rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &ersaztMethods);
140 }
141 }
142 memtraceOut = out;
143 return rc;
144}
145
146/* Deactivate memory tracing */
147int sqlite3MemTraceDeactivate(void){
148 int rc = SQLITE_OK;
149 if( memtraceBase.xMalloc!=0 ){
150 rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memtraceBase);
151 if( rc==SQLITE_OK ){
152 memset(&memtraceBase, 0, sizeof(memtraceBase));
153 }
154 }
155 memtraceOut = 0;
156 return rc;
157}
158/***** End copy/paste from ext/misc/memtrace.c ***************************/
159
drhd811d842018-10-27 21:06:44 +0000160/* libFuzzer invokes this routine with fuzzed database files (in aData).
161** This routine run SQLite against the malformed database to see if it
162** can provoke a failure or malfunction.
163*/
drh65da2852018-10-27 00:47:33 +0000164int LLVMFuzzerTestOneInput(const uint8_t *aData, size_t nByte){
165 unsigned char *a;
166 sqlite3 *db;
167 int rc;
168 int i;
drh178edcd2019-01-22 16:11:31 +0000169 sqlite3_int64 x;
drh88862d42019-02-04 19:45:26 +0000170 char *zErr = 0;
drh65da2852018-10-27 00:47:33 +0000171
drhd811d842018-10-27 21:06:44 +0000172 if( eVerbosity>=1 ){
173 printf("************** nByte=%d ***************\n", (int)nByte);
174 fflush(stdout);
175 }
drh62a88292018-12-07 03:01:07 +0000176 if( sqlite3_initialize() ) return 0;
drhad9bfa52018-10-30 15:20:35 +0000177 rc = sqlite3_open(0, &db);
drh65da2852018-10-27 00:47:33 +0000178 if( rc ) return 1;
drhad9bfa52018-10-30 15:20:35 +0000179 a = sqlite3_malloc64(nByte+1);
drh65da2852018-10-27 00:47:33 +0000180 if( a==0 ) return 1;
181 memcpy(a, aData, nByte);
182 sqlite3_deserialize(db, "main", a, nByte, nByte,
183 SQLITE_DESERIALIZE_RESIZEABLE |
184 SQLITE_DESERIALIZE_FREEONCLOSE);
drh178edcd2019-01-22 16:11:31 +0000185 x = szMax;
drhddc28c22019-02-26 18:21:08 +0000186#ifdef SQLITE_FCNTL_SIZE_LIMIT
drh178edcd2019-01-22 16:11:31 +0000187 sqlite3_file_control(db, "main", SQLITE_FCNTL_SIZE_LIMIT, &x);
drhddc28c22019-02-26 18:21:08 +0000188#endif
drh1972c8c2019-01-11 14:38:47 +0000189 if( bVdbeDebug ){
190 sqlite3_exec(db, "PRAGMA vdbe_debug=ON", 0, 0, 0);
191 }
drh65da2852018-10-27 00:47:33 +0000192 for(i=0; i<sizeof(azSql)/sizeof(azSql[0]); i++){
drhd811d842018-10-27 21:06:44 +0000193 if( eVerbosity>=1 ){
194 printf("%s\n", azSql[i]);
195 fflush(stdout);
196 }
drh88862d42019-02-04 19:45:26 +0000197 zErr = 0;
198 rc = sqlite3_exec(db, azSql[i], 0, 0, &zErr);
199 if( rc && eVerbosity>=1 ){
200 printf("-- rc=%d zErr=%s\n", rc, zErr);
201 }
202 sqlite3_free(zErr);
drh65da2852018-10-27 00:47:33 +0000203 }
drhad9bfa52018-10-30 15:20:35 +0000204 rc = sqlite3_close(db);
205 if( rc!=SQLITE_OK ){
206 fprintf(stdout, "sqlite3_close() returns %d\n", rc);
207 }
drhd811d842018-10-27 21:06:44 +0000208 if( sqlite3_memory_used()!=0 ){
drhad9bfa52018-10-30 15:20:35 +0000209 int nAlloc = 0;
210 int nNotUsed = 0;
211 sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &nAlloc, &nNotUsed, 0);
212 fprintf(stderr,"Memory leak: %lld bytes in %d allocations\n",
213 sqlite3_memory_used(), nAlloc);
drhd811d842018-10-27 21:06:44 +0000214 exit(1);
215 }
216 return 0;
217}
218
drh1972c8c2019-01-11 14:38:47 +0000219/*
220** Return the number of "v" characters in a string. Return 0 if there
221** are any characters in the string other than "v".
222*/
223static int numberOfVChar(const char *z){
224 int N = 0;
225 while( z[0] && z[0]=='v' ){
226 z++;
227 N++;
228 }
229 return z[0]==0 ? N : 0;
230}
231
drhd811d842018-10-27 21:06:44 +0000232/* libFuzzer invokes this routine once when the executable starts, to
233** process the command-line arguments.
234*/
235int LLVMFuzzerInitialize(int *pArgc, char ***pArgv){
drh1972c8c2019-01-11 14:38:47 +0000236 int i, j, n;
drhd811d842018-10-27 21:06:44 +0000237 int argc = *pArgc;
drhd811d842018-10-27 21:06:44 +0000238 char **argv = *pArgv;
drhd811d842018-10-27 21:06:44 +0000239 for(i=j=1; i<argc; i++){
240 char *z = argv[i];
241 if( z[0]=='-' ){
242 z++;
243 if( z[0]=='-' ) z++;
drh1972c8c2019-01-11 14:38:47 +0000244 if( z[0]=='v' && (n = numberOfVChar(z))>0 ){
245 eVerbosity += n;
246 continue;
247 }
248 if( strcmp(z,"vdbe-debug")==0 ){
249 bVdbeDebug = 1;
drhd811d842018-10-27 21:06:44 +0000250 continue;
251 }
drha7908822019-02-04 19:50:44 +0000252 if( strcmp(z,"memtrace")==0 ){
253 sqlite3MemTraceActivate(stdout);
254 continue;
255 }
256 if( strcmp(z,"mem")==0 ){
257 bVdbeDebug = 1;
258 continue;
259 }
drh178edcd2019-01-22 16:11:31 +0000260 if( strcmp(z,"max-db-size")==0 ){
261 if( i+1==argc ){
262 fprintf(stderr, "missing argument to %s\n", argv[i]);
263 exit(1);
264 }
265 szMax = strtol(argv[++i], 0, 0);
266 continue;
267 }
drh7e85e902019-02-20 19:06:16 +0000268#ifndef _WIN32
drh59765522019-01-21 13:47:55 +0000269 if( strcmp(z,"max-stack")==0
270 || strcmp(z,"max-data")==0
271 || strcmp(z,"max-as")==0
272 ){
drh8ed07d12019-01-20 00:03:59 +0000273 struct rlimit x,y;
drh59765522019-01-21 13:47:55 +0000274 int resource = RLIMIT_STACK;
275 char *zType = "RLIMIT_STACK";
drh8ed07d12019-01-20 00:03:59 +0000276 if( i+1==argc ){
277 fprintf(stderr, "missing argument to %s\n", argv[i]);
278 exit(1);
279 }
drh59765522019-01-21 13:47:55 +0000280 if( z[4]=='d' ){
281 resource = RLIMIT_DATA;
282 zType = "RLIMIT_DATA";
283 }
284 if( z[4]=='a' ){
285 resource = RLIMIT_AS;
286 zType = "RLIMIT_AS";
287 }
drh8ed07d12019-01-20 00:03:59 +0000288 memset(&x,0,sizeof(x));
drh59765522019-01-21 13:47:55 +0000289 getrlimit(resource, &x);
drh8ed07d12019-01-20 00:03:59 +0000290 y.rlim_cur = atoi(argv[++i]);
291 y.rlim_max = x.rlim_cur;
drh59765522019-01-21 13:47:55 +0000292 setrlimit(resource, &y);
drh8ed07d12019-01-20 00:03:59 +0000293 memset(&y,0,sizeof(y));
drh59765522019-01-21 13:47:55 +0000294 getrlimit(resource, &y);
295 printf("%s changed from %d to %d\n",
296 zType, (int)x.rlim_cur, (int)y.rlim_cur);
drh8ed07d12019-01-20 00:03:59 +0000297 continue;
298 }
drh7e85e902019-02-20 19:06:16 +0000299#endif /* _WIN32 */
drhd811d842018-10-27 21:06:44 +0000300 }
drhb10a50e2019-01-13 20:23:34 +0000301 argv[j++] = argv[i];
drhd811d842018-10-27 21:06:44 +0000302 }
drhb10a50e2019-01-13 20:23:34 +0000303 argv[j] = 0;
drhd811d842018-10-27 21:06:44 +0000304 *pArgc = j;
drh65da2852018-10-27 00:47:33 +0000305 return 0;
306}
drhe65b9c62019-01-11 13:03:06 +0000307
308#ifdef STANDALONE
309/*
310** Read an entire file into memory. Space to hold the file comes
311** from malloc().
312*/
313static unsigned char *readFile(const char *zName, int *pnByte){
314 FILE *in = fopen(zName, "rb");
315 long nIn;
316 size_t nRead;
317 unsigned char *pBuf;
318 if( in==0 ) return 0;
319 fseek(in, 0, SEEK_END);
320 nIn = ftell(in);
321 rewind(in);
322 pBuf = malloc( nIn+1 );
323 if( pBuf==0 ){ fclose(in); return 0; }
324 nRead = fread(pBuf, nIn, 1, in);
325 fclose(in);
326 if( nRead!=1 ){
327 free(pBuf);
328 return 0;
329 }
330 pBuf[nIn] = 0;
331 if( pnByte ) *pnByte = nIn;
332 return pBuf;
333}
334#endif /* STANDALONE */
335
336#ifdef STANDALONE
337int main(int argc, char **argv){
338 int i;
drhe65b9c62019-01-11 13:03:06 +0000339 LLVMFuzzerInitialize(&argc, &argv);
340 for(i=1; i<argc; i++){
341 unsigned char *pIn;
342 int nIn;
343 pIn = readFile(argv[i], &nIn);
344 if( pIn ){
345 LLVMFuzzerTestOneInput((const uint8_t*)pIn, (size_t)nIn);
346 free(pIn);
347 }
348 }
drhb10a50e2019-01-13 20:23:34 +0000349 if( eVerbosity>0 ){
drh59765522019-01-21 13:47:55 +0000350 struct rusage x;
drhb10a50e2019-01-13 20:23:34 +0000351 printf("SQLite %s\n", sqlite3_sourceid());
drh59765522019-01-21 13:47:55 +0000352 memset(&x, 0, sizeof(x));
353 if( getrusage(RUSAGE_SELF, &x)==0 ){
354 printf("Maximum RSS = %ld KB\n", x.ru_maxrss);
355 }
drhb10a50e2019-01-13 20:23:34 +0000356 }
drhe65b9c62019-01-11 13:03:06 +0000357 return 0;
358}
359#endif /*STANDALONE*/