4 ** The author disclaims copyright to this source code. In place of
5 ** a legal notice, here is a blessing:
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.
11 *************************************************************************
13 ** This program is designed for fuzz-testing SQLite database files using
14 ** the -fsanitize=fuzzer option of clang.
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.
21 ** For best results the seed database files should have these tables:
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.
28 ** Any of these tables can be virtual tables, for example FTS or RTree tables.
33 ** cp dbfuzz2-seed*.db dir
34 ** clang-6.0 -I. -g -O1 -fsanitize=fuzzer -DTHREADSAFE=0 \
35 ** -DSQLITE_ENABLE_DBSTAT_VTAB dbfuzz2.c sqlite3.c -ldl
47 #include <sys/resource.h>
52 ** This is the is the SQL that is run against the database.
54 static const char *azSql
[] = {
55 "PRAGMA integrity_check;",
56 "SELECT * FROM sqlite_schema;",
57 "SELECT sum(length(name)) FROM dbstat;",
58 "UPDATE t1 SET b=a, a=b WHERE a<b;",
59 "ALTER TABLE t1 RENAME TO alkjalkjdfiiiwuer987lkjwer82mx97sf98788s9789s;",
60 "INSERT INTO t3 SELECT * FROM t2;",
61 "DELETE FROM t3 WHERE x IN (SELECT x FROM t4);",
67 /* Output verbosity level. 0 means complete silence */
70 /* True to activate PRAGMA vdbe_debug=on */
71 static int bVdbeDebug
= 0;
73 /* Maximum size of the in-memory database file */
74 static sqlite3_int64 szMax
= 104857600;
76 /* Progress handler callback data */
77 static int nCb
= 0; /* Number of callbacks seen so far */
78 static int mxCb
= 250000; /* Maximum allowed callbacks */
80 /***** Copy/paste from ext/misc/memtrace.c ***************************/
81 /* The original memory allocation routines */
82 static sqlite3_mem_methods memtraceBase
;
83 static FILE *memtraceOut
;
85 /* Methods that trace memory allocations */
86 static void *memtraceMalloc(int n
){
88 fprintf(memtraceOut
, "MEMTRACE: allocate %d bytes\n",
89 memtraceBase
.xRoundup(n
));
91 return memtraceBase
.xMalloc(n
);
93 static void memtraceFree(void *p
){
96 fprintf(memtraceOut
, "MEMTRACE: free %d bytes\n", memtraceBase
.xSize(p
));
98 memtraceBase
.xFree(p
);
100 static void *memtraceRealloc(void *p
, int n
){
101 if( p
==0 ) return memtraceMalloc(n
);
107 fprintf(memtraceOut
, "MEMTRACE: resize %d -> %d bytes\n",
108 memtraceBase
.xSize(p
), memtraceBase
.xRoundup(n
));
110 return memtraceBase
.xRealloc(p
, n
);
112 static int memtraceSize(void *p
){
113 return memtraceBase
.xSize(p
);
115 static int memtraceRoundup(int n
){
116 return memtraceBase
.xRoundup(n
);
118 static int memtraceInit(void *p
){
119 return memtraceBase
.xInit(p
);
121 static void memtraceShutdown(void *p
){
122 memtraceBase
.xShutdown(p
);
125 /* The substitute memory allocator */
126 static sqlite3_mem_methods ersaztMethods
= {
136 /* Begin tracing memory allocations to out. */
137 int sqlite3MemTraceActivate(FILE *out
){
139 if( memtraceBase
.xMalloc
==0 ){
140 rc
= sqlite3_config(SQLITE_CONFIG_GETMALLOC
, &memtraceBase
);
142 rc
= sqlite3_config(SQLITE_CONFIG_MALLOC
, &ersaztMethods
);
149 /* Deactivate memory tracing */
150 int sqlite3MemTraceDeactivate(void){
152 if( memtraceBase
.xMalloc
!=0 ){
153 rc
= sqlite3_config(SQLITE_CONFIG_MALLOC
, &memtraceBase
);
155 memset(&memtraceBase
, 0, sizeof(memtraceBase
));
161 /***** End copy/paste from ext/misc/memtrace.c ***************************/
164 ** Progress handler callback
166 ** Count the number of callbacks and cause an abort once the limit is
169 static int progress_handler(void *pNotUsed
){
171 if( nCb
<mxCb
) return 0;
173 printf("-- Progress limit of %d reached\n", mxCb
);
178 /* libFuzzer invokes this routine with fuzzed database files (in aData).
179 ** This routine run SQLite against the malformed database to see if it
180 ** can provoke a failure or malfunction.
182 int LLVMFuzzerTestOneInput(const uint8_t *aData
, size_t nByte
){
191 printf("************** nByte=%d ***************\n", (int)nByte
);
194 if( sqlite3_initialize() ) return 0;
195 rc
= sqlite3_open(0, &db
);
197 a
= sqlite3_malloc64(nByte
+1);
199 memcpy(a
, aData
, nByte
);
200 sqlite3_deserialize(db
, "main", a
, nByte
, nByte
,
201 SQLITE_DESERIALIZE_RESIZEABLE
|
202 SQLITE_DESERIALIZE_FREEONCLOSE
);
204 #ifdef SQLITE_FCNTL_SIZE_LIMIT
205 sqlite3_file_control(db
, "main", SQLITE_FCNTL_SIZE_LIMIT
, &x
);
208 sqlite3_exec(db
, "PRAGMA vdbe_debug=ON", 0, 0, 0);
211 sqlite3_progress_handler(db
, 10, progress_handler
, 0);
213 #ifdef SQLITE_TESTCTRL_PRNG_SEED
214 sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SEED
, 1, db
);
216 for(i
=0; i
<sizeof(azSql
)/sizeof(azSql
[0]); i
++){
218 printf("%s\n", azSql
[i
]);
223 rc
= sqlite3_exec(db
, azSql
[i
], 0, 0, &zErr
);
224 if( rc
&& eVerbosity
>=1 ){
225 printf("-- rc=%d zErr=%s\n", rc
, zErr
);
229 rc
= sqlite3_close(db
);
231 fprintf(stdout
, "sqlite3_close() returns %d\n", rc
);
233 if( sqlite3_memory_used()!=0 ){
236 sqlite3_status(SQLITE_STATUS_MALLOC_COUNT
, &nAlloc
, &nNotUsed
, 0);
237 fprintf(stderr
,"Memory leak: %lld bytes in %d allocations\n",
238 sqlite3_memory_used(), nAlloc
);
245 ** Return the number of "v" characters in a string. Return 0 if there
246 ** are any characters in the string other than "v".
248 static int numberOfVChar(const char *z
){
250 while( z
[0] && z
[0]=='v' ){
254 return z
[0]==0 ? N
: 0;
257 /* libFuzzer invokes this routine once when the executable starts, to
258 ** process the command-line arguments.
260 int LLVMFuzzerInitialize(int *pArgc
, char ***pArgv
){
263 char **argv
= *pArgv
;
264 for(i
=j
=1; i
<argc
; i
++){
269 if( z
[0]=='v' && (n
= numberOfVChar(z
))>0 ){
273 if( strcmp(z
,"vdbe-debug")==0 ){
277 if( strcmp(z
,"limit")==0 ){
279 fprintf(stderr
, "missing argument to %s\n", argv
[i
]);
282 mxCb
= strtol(argv
[++i
], 0, 0);
285 if( strcmp(z
,"memtrace")==0 ){
286 sqlite3MemTraceActivate(stdout
);
289 if( strcmp(z
,"max-db-size")==0 ){
291 fprintf(stderr
, "missing argument to %s\n", argv
[i
]);
294 szMax
= strtol(argv
[++i
], 0, 0);
297 if( strcmp(z
, "lookaside")==0 ){
301 "--lookaside requires two arguments: slot-size num-slots\n");
304 sz
= atoi(argv
[++i
]);
305 nSlot
= atoi(argv
[++i
]);
306 sqlite3_config(SQLITE_CONFIG_LOOKASIDE
, sz
, nSlot
);
310 if( strcmp(z
,"max-stack")==0
311 || strcmp(z
,"max-data")==0
312 || strcmp(z
,"max-as")==0
315 int resource
= RLIMIT_STACK
;
316 char *zType
= "RLIMIT_STACK";
318 fprintf(stderr
, "missing argument to %s\n", argv
[i
]);
322 resource
= RLIMIT_DATA
;
323 zType
= "RLIMIT_DATA";
326 resource
= RLIMIT_AS
;
329 memset(&x
,0,sizeof(x
));
330 getrlimit(resource
, &x
);
331 y
.rlim_cur
= atoi(argv
[++i
]);
332 y
.rlim_max
= x
.rlim_cur
;
333 setrlimit(resource
, &y
);
334 memset(&y
,0,sizeof(y
));
335 getrlimit(resource
, &y
);
336 printf("%s changed from %d to %d\n",
337 zType
, (int)x
.rlim_cur
, (int)y
.rlim_cur
);
351 ** Read an entire file into memory. Space to hold the file comes
354 static unsigned char *readFile(const char *zName
, int *pnByte
){
355 FILE *in
= fopen(zName
, "rb");
359 if( in
==0 ) return 0;
360 fseek(in
, 0, SEEK_END
);
363 pBuf
= malloc( nIn
+1 );
364 if( pBuf
==0 ){ fclose(in
); return 0; }
365 nRead
= fread(pBuf
, nIn
, 1, in
);
372 if( pnByte
) *pnByte
= nIn
;
375 #endif /* STANDALONE */
378 int main(int argc
, char **argv
){
380 LLVMFuzzerInitialize(&argc
, &argv
);
381 for(i
=1; i
<argc
; i
++){
384 pIn
= readFile(argv
[i
], &nIn
);
386 LLVMFuzzerTestOneInput((const uint8_t*)pIn
, (size_t)nIn
);
393 printf("SQLite %s\n", sqlite3_sourceid());
394 memset(&x
, 0, sizeof(x
));
395 if( getrusage(RUSAGE_SELF
, &x
)==0 ){
396 printf("Maximum RSS = %ld KB\n", x
.ru_maxrss
);
402 #endif /*STANDALONE*/