blob: ff2125d0c665cf5461dcf7d00c75a614e3d5a93a [file] [log] [blame]
drh268e72f2015-04-17 14:30:49 +00001/*
2** 2015-04-17
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 is a utility program designed to aid running the SQLite library
14** against an external fuzzer, such as American Fuzzy Lop (AFL)
15** (http://lcamtuf.coredump.cx/afl/). Basically, this program reads
16** SQL text from standard input and passes it through to SQLite for evaluation,
17** just like the "sqlite3" command-line shell. Differences from the
18** command-line shell:
19**
20** (1) The complex "dot-command" extensions are omitted. This
21** prevents the fuzzer from discovering that it can run things
22** like ".shell rm -rf ~"
23**
24** (2) The database is opened with the SQLITE_OPEN_MEMORY flag so that
25** no disk I/O from the database is permitted. The ATTACH command
26** with a filename still uses an in-memory database.
27**
28** (3) The main in-memory database can be initialized from a template
29** disk database so that the fuzzer starts with a database containing
30** content.
31**
32** (4) The eval() SQL function is added, allowing the fuzzer to do
33** interesting recursive operations.
drhf34e9aa2015-04-20 12:50:13 +000034**
35** 2015-04-20: The input text can be divided into separate SQL chunks using
36** lines of the form:
37**
38** |****<...>****|
39**
40** where the "..." is arbitrary text, except the "|" should really be "/".
41** ("|" is used here to avoid compiler warnings about nested comments.)
drh875bafa2015-04-24 14:47:59 +000042** A separate in-memory SQLite database is created to run each chunk of SQL.
43** This feature allows the "queue" of AFL to be captured into a single big
drhf34e9aa2015-04-20 12:50:13 +000044** file using a command like this:
45**
46** (for i in id:*; do echo '|****<'$i'>****|'; cat $i; done) >~/all-queue.txt
47**
48** (Once again, change the "|" to "/") Then all elements of the AFL queue
drh4a74d072015-04-20 18:58:38 +000049** can be run in a single go (for regression testing, for example) by typing:
drhf34e9aa2015-04-20 12:50:13 +000050**
drh875bafa2015-04-24 14:47:59 +000051** fuzzershell -f ~/all-queue.txt
drhf34e9aa2015-04-20 12:50:13 +000052**
53** After running each chunk of SQL, the database connection is closed. The
54** program aborts if the close fails or if there is any unfreed memory after
55** the close.
drh875bafa2015-04-24 14:47:59 +000056**
57** New cases can be appended to all-queue.txt at any time. If redundant cases
58** are added, that can be eliminated by running:
59**
60** fuzzershell -f ~/all-queue.txt --unique-cases ~/unique-cases.txt
61**
drh268e72f2015-04-17 14:30:49 +000062*/
63#include <stdio.h>
64#include <stdlib.h>
65#include <string.h>
66#include <stdarg.h>
drh4a74d072015-04-20 18:58:38 +000067#include <ctype.h>
drh268e72f2015-04-17 14:30:49 +000068#include "sqlite3.h"
69
70/*
71** All global variables are gathered into the "g" singleton.
72*/
73struct GlobalVars {
drh048810b2015-04-24 23:45:23 +000074 const char *zArgv0; /* Name of program */
75 sqlite3_mem_methods sOrigMem; /* Original memory methods */
76 sqlite3_mem_methods sOomMem; /* Memory methods with OOM simulator */
77 int iOomCntdown; /* Memory fails on 1 to 0 transition */
78 int nOomFault; /* Increments for each OOM fault */
79 int bOomOnce; /* Fail just once if true */
80 int bOomEnable; /* True to enable OOM simulation */
81 int nOomBrkpt; /* Number of calls to oomFault() */
drh0ee751f2015-04-25 11:19:51 +000082 char zTestName[100]; /* Name of current test */
drh268e72f2015-04-17 14:30:49 +000083} g;
84
drh048810b2015-04-24 23:45:23 +000085/*
86** This routine is called when a simulated OOM occurs. It exists as a
87** convenient place to set a debugger breakpoint.
88*/
89static void oomFault(void){
90 g.nOomBrkpt++;
91}
drh268e72f2015-04-17 14:30:49 +000092
93
drh048810b2015-04-24 23:45:23 +000094/* Versions of malloc() and realloc() that simulate OOM conditions */
95static void *oomMalloc(int nByte){
96 if( nByte>0 && g.bOomEnable && g.iOomCntdown>0 ){
97 g.iOomCntdown--;
98 if( g.iOomCntdown==0 ){
99 if( g.nOomFault==0 ) oomFault();
100 g.nOomFault++;
101 if( !g.bOomOnce ) g.iOomCntdown = 1;
102 return 0;
103 }
104 }
105 return g.sOrigMem.xMalloc(nByte);
106}
107static void *oomRealloc(void *pOld, int nByte){
108 if( nByte>0 && g.bOomEnable && g.iOomCntdown>0 ){
109 g.iOomCntdown--;
110 if( g.iOomCntdown==0 ){
111 if( g.nOomFault==0 ) oomFault();
112 g.nOomFault++;
113 if( !g.bOomOnce ) g.iOomCntdown = 1;
114 return 0;
115 }
116 }
117 return g.sOrigMem.xRealloc(pOld, nByte);
118}
119
drh268e72f2015-04-17 14:30:49 +0000120/*
121** Print an error message and abort in such a way to indicate to the
122** fuzzer that this counts as a crash.
123*/
124static void abendError(const char *zFormat, ...){
125 va_list ap;
126 fprintf(stderr, "%s: ", g.zArgv0);
127 va_start(ap, zFormat);
128 vfprintf(stderr, zFormat, ap);
129 va_end(ap);
130 fprintf(stderr, "\n");
131 abort();
132}
133/*
134** Print an error message and quit, but not in a way that would look
135** like a crash.
136*/
137static void fatalError(const char *zFormat, ...){
138 va_list ap;
139 fprintf(stderr, "%s: ", g.zArgv0);
140 va_start(ap, zFormat);
141 vfprintf(stderr, zFormat, ap);
142 va_end(ap);
143 fprintf(stderr, "\n");
144 exit(1);
145}
146
147/*
drh4a74d072015-04-20 18:58:38 +0000148** Evaluate some SQL. Abort if unable.
149*/
150static void sqlexec(sqlite3 *db, const char *zFormat, ...){
151 va_list ap;
152 char *zSql;
153 char *zErrMsg = 0;
154 int rc;
155 va_start(ap, zFormat);
156 zSql = sqlite3_vmprintf(zFormat, ap);
157 va_end(ap);
158 rc = sqlite3_exec(db, zSql, 0, 0, &zErrMsg);
159 if( rc ) abendError("failed sql [%s]: %s", zSql, zErrMsg);
160 sqlite3_free(zSql);
161}
162
163/*
drh268e72f2015-04-17 14:30:49 +0000164** This callback is invoked by sqlite3_log().
165*/
166static void shellLog(void *pNotUsed, int iErrCode, const char *zMsg){
167 printf("LOG: (%d) %s\n", iErrCode, zMsg);
drh9f18f742015-04-25 00:20:15 +0000168 fflush(stdout);
drh268e72f2015-04-17 14:30:49 +0000169}
drh0ee751f2015-04-25 11:19:51 +0000170static void shellLogNoop(void *pNotUsed, int iErrCode, const char *zMsg){
171 return;
172}
drh268e72f2015-04-17 14:30:49 +0000173
174/*
175** This callback is invoked by sqlite3_exec() to return query results.
176*/
177static int execCallback(void *NotUsed, int argc, char **argv, char **colv){
178 int i;
179 static unsigned cnt = 0;
180 printf("ROW #%u:\n", ++cnt);
181 for(i=0; i<argc; i++){
182 printf(" %s=", colv[i]);
183 if( argv[i] ){
184 printf("[%s]\n", argv[i]);
185 }else{
186 printf("NULL\n");
187 }
188 }
drh9f18f742015-04-25 00:20:15 +0000189 fflush(stdout);
drh268e72f2015-04-17 14:30:49 +0000190 return 0;
191}
drh1cbb7fa2015-04-24 13:00:59 +0000192static int execNoop(void *NotUsed, int argc, char **argv, char **colv){
193 return 0;
194}
drh268e72f2015-04-17 14:30:49 +0000195
drh61a0d6b2015-04-24 18:31:12 +0000196#ifndef SQLITE_OMIT_TRACE
drh268e72f2015-04-17 14:30:49 +0000197/*
198** This callback is invoked by sqlite3_trace() as each SQL statement
199** starts.
200*/
201static void traceCallback(void *NotUsed, const char *zMsg){
202 printf("TRACE: %s\n", zMsg);
drh9f18f742015-04-25 00:20:15 +0000203 fflush(stdout);
drh268e72f2015-04-17 14:30:49 +0000204}
drh0ee751f2015-04-25 11:19:51 +0000205static void traceNoop(void *NotUsed, const char *zMsg){
206 return;
207}
drh61a0d6b2015-04-24 18:31:12 +0000208#endif
drh268e72f2015-04-17 14:30:49 +0000209
210/***************************************************************************
211** eval() implementation copied from ../ext/misc/eval.c
212*/
213/*
214** Structure used to accumulate the output
215*/
216struct EvalResult {
217 char *z; /* Accumulated output */
218 const char *zSep; /* Separator */
219 int szSep; /* Size of the separator string */
220 sqlite3_int64 nAlloc; /* Number of bytes allocated for z[] */
221 sqlite3_int64 nUsed; /* Number of bytes of z[] actually used */
222};
223
224/*
225** Callback from sqlite_exec() for the eval() function.
226*/
227static int callback(void *pCtx, int argc, char **argv, char **colnames){
228 struct EvalResult *p = (struct EvalResult*)pCtx;
229 int i;
230 for(i=0; i<argc; i++){
231 const char *z = argv[i] ? argv[i] : "";
232 size_t sz = strlen(z);
233 if( (sqlite3_int64)sz+p->nUsed+p->szSep+1 > p->nAlloc ){
234 char *zNew;
235 p->nAlloc = p->nAlloc*2 + sz + p->szSep + 1;
236 /* Using sqlite3_realloc64() would be better, but it is a recent
237 ** addition and will cause a segfault if loaded by an older version
238 ** of SQLite. */
239 zNew = p->nAlloc<=0x7fffffff ? sqlite3_realloc(p->z, (int)p->nAlloc) : 0;
240 if( zNew==0 ){
241 sqlite3_free(p->z);
242 memset(p, 0, sizeof(*p));
243 return 1;
244 }
245 p->z = zNew;
246 }
247 if( p->nUsed>0 ){
248 memcpy(&p->z[p->nUsed], p->zSep, p->szSep);
249 p->nUsed += p->szSep;
250 }
251 memcpy(&p->z[p->nUsed], z, sz);
252 p->nUsed += sz;
253 }
254 return 0;
255}
256
257/*
258** Implementation of the eval(X) and eval(X,Y) SQL functions.
259**
260** Evaluate the SQL text in X. Return the results, using string
261** Y as the separator. If Y is omitted, use a single space character.
262*/
263static void sqlEvalFunc(
264 sqlite3_context *context,
265 int argc,
266 sqlite3_value **argv
267){
268 const char *zSql;
269 sqlite3 *db;
270 char *zErr = 0;
271 int rc;
272 struct EvalResult x;
273
274 memset(&x, 0, sizeof(x));
275 x.zSep = " ";
276 zSql = (const char*)sqlite3_value_text(argv[0]);
277 if( zSql==0 ) return;
278 if( argc>1 ){
279 x.zSep = (const char*)sqlite3_value_text(argv[1]);
280 if( x.zSep==0 ) return;
281 }
282 x.szSep = (int)strlen(x.zSep);
283 db = sqlite3_context_db_handle(context);
284 rc = sqlite3_exec(db, zSql, callback, &x, &zErr);
285 if( rc!=SQLITE_OK ){
286 sqlite3_result_error(context, zErr, -1);
287 sqlite3_free(zErr);
288 }else if( x.zSep==0 ){
289 sqlite3_result_error_nomem(context);
290 sqlite3_free(x.z);
291 }else{
292 sqlite3_result_text(context, x.z, (int)x.nUsed, sqlite3_free);
293 }
294}
295/* End of the eval() implementation
296******************************************************************************/
297
298/*
299** Print sketchy documentation for this utility program
300*/
301static void showHelp(void){
302 printf("Usage: %s [options]\n", g.zArgv0);
303 printf(
304"Read SQL text from standard input and evaluate it.\n"
305"Options:\n"
drh875bafa2015-04-24 14:47:59 +0000306" --autovacuum Enable AUTOVACUUM mode\n"
307" -f FILE Read SQL text from FILE instead of standard input\n"
308" --heap SZ MIN Memory allocator uses SZ bytes & min allocation MIN\n"
309" --help Show this help text\n"
310" --initdb DBFILE Initialize the in-memory database using template DBFILE\n"
311" --lookaside N SZ Configure lookaside for N slots of SZ bytes each\n"
drh048810b2015-04-24 23:45:23 +0000312" --oom Run each test multiple times in a simulated OOM loop\n"
drh875bafa2015-04-24 14:47:59 +0000313" --pagesize N Set the page size to N\n"
314" --pcache N SZ Configure N pages of pagecache each of size SZ bytes\n"
315" -q Reduced output\n"
316" --quiet Reduced output\n"
317" --scratch N SZ Configure scratch memory for N slots of SZ bytes each\n"
318" --unique-cases FILE Write all unique test cases to FILE\n"
319" --utf16be Set text encoding to UTF-16BE\n"
320" --utf16le Set text encoding to UTF-16LE\n"
321" -v Increased output\n"
322" --verbose Increased output\n"
drh268e72f2015-04-17 14:30:49 +0000323 );
324}
325
drh4a74d072015-04-20 18:58:38 +0000326/*
327** Return the value of a hexadecimal digit. Return -1 if the input
328** is not a hex digit.
329*/
330static int hexDigitValue(char c){
331 if( c>='0' && c<='9' ) return c - '0';
332 if( c>='a' && c<='f' ) return c - 'a' + 10;
333 if( c>='A' && c<='F' ) return c - 'A' + 10;
334 return -1;
335}
336
337/*
338** Interpret zArg as an integer value, possibly with suffixes.
339*/
340static int integerValue(const char *zArg){
341 sqlite3_int64 v = 0;
342 static const struct { char *zSuffix; int iMult; } aMult[] = {
343 { "KiB", 1024 },
344 { "MiB", 1024*1024 },
345 { "GiB", 1024*1024*1024 },
346 { "KB", 1000 },
347 { "MB", 1000000 },
348 { "GB", 1000000000 },
349 { "K", 1000 },
350 { "M", 1000000 },
351 { "G", 1000000000 },
352 };
353 int i;
354 int isNeg = 0;
355 if( zArg[0]=='-' ){
356 isNeg = 1;
357 zArg++;
358 }else if( zArg[0]=='+' ){
359 zArg++;
360 }
361 if( zArg[0]=='0' && zArg[1]=='x' ){
362 int x;
363 zArg += 2;
364 while( (x = hexDigitValue(zArg[0]))>=0 ){
365 v = (v<<4) + x;
366 zArg++;
367 }
368 }else{
369 while( isdigit(zArg[0]) ){
370 v = v*10 + zArg[0] - '0';
371 zArg++;
372 }
373 }
374 for(i=0; i<sizeof(aMult)/sizeof(aMult[0]); i++){
375 if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
376 v *= aMult[i].iMult;
377 break;
378 }
379 }
380 if( v>0x7fffffff ) abendError("parameter too large - max 2147483648");
381 return (int)(isNeg? -v : v);
382}
383
drh9985dab2015-04-20 22:36:49 +0000384/*
385** Various operating modes
386*/
387#define FZMODE_Generic 1
388#define FZMODE_Strftime 2
389#define FZMODE_Printf 3
390#define FZMODE_Glob 4
391
drh268e72f2015-04-17 14:30:49 +0000392
393int main(int argc, char **argv){
394 char *zIn = 0; /* Input text */
395 int nAlloc = 0; /* Number of bytes allocated for zIn[] */
396 int nIn = 0; /* Number of bytes of zIn[] used */
397 size_t got; /* Bytes read from input */
398 FILE *in = stdin; /* Where to read SQL text from */
399 int rc = SQLITE_OK; /* Result codes from API functions */
400 int i; /* Loop counter */
drhf34e9aa2015-04-20 12:50:13 +0000401 int iNext; /* Next block of SQL */
drh268e72f2015-04-17 14:30:49 +0000402 sqlite3 *db; /* Open database */
drhf34e9aa2015-04-20 12:50:13 +0000403 sqlite3 *dbInit = 0; /* On-disk database used to initialize the in-memory db */
drh268e72f2015-04-17 14:30:49 +0000404 const char *zInitDb = 0;/* Name of the initialization database file */
405 char *zErrMsg = 0; /* Error message returned from sqlite3_exec() */
drh4a74d072015-04-20 18:58:38 +0000406 const char *zEncoding = 0; /* --utf16be or --utf16le */
407 int nHeap = 0, mnHeap = 0; /* Heap size from --heap */
408 int nLook = 0, szLook = 0; /* --lookaside configuration */
409 int nPCache = 0, szPCache = 0;/* --pcache configuration */
410 int nScratch = 0, szScratch=0;/* --scratch configuration */
411 int pageSize = 0; /* Desired page size. 0 means default */
412 void *pHeap = 0; /* Allocated heap space */
413 void *pLook = 0; /* Allocated lookaside space */
414 void *pPCache = 0; /* Allocated storage for pcache */
415 void *pScratch = 0; /* Allocated storage for scratch */
416 int doAutovac = 0; /* True for --autovacuum */
drh9985dab2015-04-20 22:36:49 +0000417 char *zSql; /* SQL to run */
418 char *zToFree = 0; /* Call sqlite3_free() on this afte running zSql */
419 int iMode = FZMODE_Generic; /* Operating mode */
drh0ba51082015-04-22 13:16:46 +0000420 const char *zCkGlob = 0; /* Inputs must match this glob */
drh1cbb7fa2015-04-24 13:00:59 +0000421 int verboseFlag = 0; /* --verbose or -v flag */
422 int quietFlag = 0; /* --quiet or -q flag */
423 int nTest = 0; /* Number of test cases run */
424 int multiTest = 0; /* True if there will be multiple test cases */
425 int lastPct = -1; /* Previous percentage done output */
drh875bafa2015-04-24 14:47:59 +0000426 sqlite3 *dataDb = 0; /* Database holding compacted input data */
427 sqlite3_stmt *pStmt = 0; /* Statement to insert testcase into dataDb */
428 const char *zDataOut = 0; /* Write compacted data to this output file */
drhe1a71a52015-04-24 16:09:12 +0000429 int nHeader = 0; /* Bytes of header comment text on input file */
drh048810b2015-04-24 23:45:23 +0000430 int oomFlag = 0; /* --oom */
431 int oomCnt = 0; /* Counter for the OOM loop */
432 char zErrBuf[200]; /* Space for the error message */
433 const char *zFailCode; /* Value of the TEST_FAILURE environment var */
drh4a74d072015-04-20 18:58:38 +0000434
drh268e72f2015-04-17 14:30:49 +0000435
drh048810b2015-04-24 23:45:23 +0000436 zFailCode = getenv("TEST_FAILURE");
drh268e72f2015-04-17 14:30:49 +0000437 g.zArgv0 = argv[0];
438 for(i=1; i<argc; i++){
439 const char *z = argv[i];
440 if( z[0]=='-' ){
441 z++;
442 if( z[0]=='-' ) z++;
drh4a74d072015-04-20 18:58:38 +0000443 if( strcmp(z,"autovacuum")==0 ){
444 doAutovac = 1;
drh268e72f2015-04-17 14:30:49 +0000445 }else
446 if( strcmp(z, "f")==0 && i+1<argc ){
447 if( in!=stdin ) abendError("only one -f allowed");
448 in = fopen(argv[++i],"rb");
449 if( in==0 ) abendError("cannot open input file \"%s\"", argv[i]);
450 }else
drh4a74d072015-04-20 18:58:38 +0000451 if( strcmp(z,"heap")==0 ){
452 if( i>=argc-2 ) abendError("missing arguments on %s\n", argv[i]);
453 nHeap = integerValue(argv[i+1]);
454 mnHeap = integerValue(argv[i+2]);
455 i += 2;
456 }else
457 if( strcmp(z,"help")==0 ){
458 showHelp();
459 return 0;
460 }else
drh268e72f2015-04-17 14:30:49 +0000461 if( strcmp(z, "initdb")==0 && i+1<argc ){
462 if( zInitDb!=0 ) abendError("only one --initdb allowed");
463 zInitDb = argv[++i];
464 }else
drh4a74d072015-04-20 18:58:38 +0000465 if( strcmp(z,"lookaside")==0 ){
466 if( i>=argc-2 ) abendError("missing arguments on %s", argv[i]);
467 nLook = integerValue(argv[i+1]);
468 szLook = integerValue(argv[i+2]);
469 i += 2;
470 }else
drh9985dab2015-04-20 22:36:49 +0000471 if( strcmp(z,"mode")==0 ){
472 if( i>=argc-1 ) abendError("missing argument on %s", argv[i]);
473 z = argv[++i];
474 if( strcmp(z,"generic")==0 ){
475 iMode = FZMODE_Printf;
drh0ba51082015-04-22 13:16:46 +0000476 zCkGlob = 0;
drh9985dab2015-04-20 22:36:49 +0000477 }else if( strcmp(z, "glob")==0 ){
478 iMode = FZMODE_Glob;
drh0ba51082015-04-22 13:16:46 +0000479 zCkGlob = "'*','*'";
drh9985dab2015-04-20 22:36:49 +0000480 }else if( strcmp(z, "printf")==0 ){
481 iMode = FZMODE_Printf;
drh0ba51082015-04-22 13:16:46 +0000482 zCkGlob = "'*',*";
drh9985dab2015-04-20 22:36:49 +0000483 }else if( strcmp(z, "strftime")==0 ){
484 iMode = FZMODE_Strftime;
drh0ba51082015-04-22 13:16:46 +0000485 zCkGlob = "'*',*";
drh9985dab2015-04-20 22:36:49 +0000486 }else{
487 abendError("unknown --mode: %s", z);
488 }
489 }else
drh048810b2015-04-24 23:45:23 +0000490 if( strcmp(z,"oom")==0 ){
491 oomFlag = 1;
492 }else
drh4a74d072015-04-20 18:58:38 +0000493 if( strcmp(z,"pagesize")==0 ){
494 if( i>=argc-1 ) abendError("missing argument on %s", argv[i]);
495 pageSize = integerValue(argv[++i]);
496 }else
497 if( strcmp(z,"pcache")==0 ){
498 if( i>=argc-2 ) abendError("missing arguments on %s", argv[i]);
499 nPCache = integerValue(argv[i+1]);
500 szPCache = integerValue(argv[i+2]);
501 i += 2;
502 }else
drh1cbb7fa2015-04-24 13:00:59 +0000503 if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){
504 quietFlag = 1;
505 verboseFlag = 0;
506 }else
drh4a74d072015-04-20 18:58:38 +0000507 if( strcmp(z,"scratch")==0 ){
508 if( i>=argc-2 ) abendError("missing arguments on %s", argv[i]);
509 nScratch = integerValue(argv[i+1]);
510 szScratch = integerValue(argv[i+2]);
511 i += 2;
512 }else
drh875bafa2015-04-24 14:47:59 +0000513 if( strcmp(z, "unique-cases")==0 ){
514 if( i>=argc-1 ) abendError("missing arguments on %s", argv[i]);
515 if( zDataOut ) abendError("only one --minimize allowed");
516 zDataOut = argv[++i];
517 }else
drh4a74d072015-04-20 18:58:38 +0000518 if( strcmp(z,"utf16le")==0 ){
519 zEncoding = "utf16le";
520 }else
521 if( strcmp(z,"utf16be")==0 ){
522 zEncoding = "utf16be";
523 }else
drh1cbb7fa2015-04-24 13:00:59 +0000524 if( strcmp(z,"verbose")==0 || strcmp(z,"v")==0 ){
525 quietFlag = 0;
526 verboseFlag = 1;
527 }else
drh268e72f2015-04-17 14:30:49 +0000528 {
529 abendError("unknown option: %s", argv[i]);
530 }
531 }else{
532 abendError("unknown argument: %s", argv[i]);
533 }
534 }
drh0ee751f2015-04-25 11:19:51 +0000535 sqlite3_config(SQLITE_CONFIG_LOG, verboseFlag ? shellLog : shellLogNoop, 0);
drh4a74d072015-04-20 18:58:38 +0000536 if( nHeap>0 ){
537 pHeap = malloc( nHeap );
538 if( pHeap==0 ) fatalError("cannot allocate %d-byte heap\n", nHeap);
539 rc = sqlite3_config(SQLITE_CONFIG_HEAP, pHeap, nHeap, mnHeap);
540 if( rc ) abendError("heap configuration failed: %d\n", rc);
541 }
drh048810b2015-04-24 23:45:23 +0000542 if( oomFlag ){
543 sqlite3_config(SQLITE_CONFIG_GETMALLOC, &g.sOrigMem);
544 g.sOomMem = g.sOrigMem;
545 g.sOomMem.xMalloc = oomMalloc;
546 g.sOomMem.xRealloc = oomRealloc;
547 sqlite3_config(SQLITE_CONFIG_MALLOC, &g.sOomMem);
548 }
drh4a74d072015-04-20 18:58:38 +0000549 if( nLook>0 ){
550 sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 0, 0);
551 if( szLook>0 ){
552 pLook = malloc( nLook*szLook );
553 if( pLook==0 ) fatalError("out of memory");
554 }
555 }
556 if( nScratch>0 && szScratch>0 ){
557 pScratch = malloc( nScratch*(sqlite3_int64)szScratch );
558 if( pScratch==0 ) fatalError("cannot allocate %lld-byte scratch",
559 nScratch*(sqlite3_int64)szScratch);
560 rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, pScratch, szScratch, nScratch);
561 if( rc ) abendError("scratch configuration failed: %d\n", rc);
562 }
563 if( nPCache>0 && szPCache>0 ){
564 pPCache = malloc( nPCache*(sqlite3_int64)szPCache );
565 if( pPCache==0 ) fatalError("cannot allocate %lld-byte pcache",
566 nPCache*(sqlite3_int64)szPCache);
567 rc = sqlite3_config(SQLITE_CONFIG_PAGECACHE, pPCache, szPCache, nPCache);
568 if( rc ) abendError("pcache configuration failed: %d", rc);
569 }
drh268e72f2015-04-17 14:30:49 +0000570 while( !feof(in) ){
drhf34e9aa2015-04-20 12:50:13 +0000571 nAlloc += nAlloc+1000;
572 zIn = realloc(zIn, nAlloc);
drh268e72f2015-04-17 14:30:49 +0000573 if( zIn==0 ) fatalError("out of memory");
574 got = fread(zIn+nIn, 1, nAlloc-nIn-1, in);
575 nIn += (int)got;
576 zIn[nIn] = 0;
577 if( got==0 ) break;
578 }
drh875bafa2015-04-24 14:47:59 +0000579 if( in!=stdin ) fclose(in);
580 if( zDataOut ){
581 rc = sqlite3_open(":memory:", &dataDb);
582 if( rc ) abendError("cannot open :memory: database");
583 rc = sqlite3_exec(dataDb,
584 "CREATE TABLE testcase(sql BLOB PRIMARY KEY) WITHOUT ROWID;",0,0,0);
585 if( rc ) abendError("%s", sqlite3_errmsg(dataDb));
586 rc = sqlite3_prepare_v2(dataDb, "INSERT OR IGNORE INTO testcase(sql)VALUES(?1)",
587 -1, &pStmt, 0);
588 if( rc ) abendError("%s", sqlite3_errmsg(dataDb));
589 }
drhf34e9aa2015-04-20 12:50:13 +0000590 if( zInitDb ){
591 rc = sqlite3_open_v2(zInitDb, &dbInit, SQLITE_OPEN_READONLY, 0);
592 if( rc!=SQLITE_OK ){
593 abendError("unable to open initialization database \"%s\"", zInitDb);
594 }
drh268e72f2015-04-17 14:30:49 +0000595 }
drhe1a71a52015-04-24 16:09:12 +0000596 for(i=0; i<nIn; i=iNext+1){ /* Skip initial lines beginning with '#' */
597 if( zIn[i]!='#' ) break;
598 for(iNext=i+1; iNext<nIn && zIn[iNext]!='\n'; iNext++){}
599 }
600 nHeader = i;
601 for(nTest=0; i<nIn; i=iNext, nTest++){
drhf34e9aa2015-04-20 12:50:13 +0000602 char cSaved;
603 if( strncmp(&zIn[i], "/****<",6)==0 ){
604 char *z = strstr(&zIn[i], ">****/");
605 if( z ){
606 z += 6;
drh0ee751f2015-04-25 11:19:51 +0000607 sqlite3_snprintf(sizeof(g.zTestName), g.zTestName, "%.*",
608 (int)(z-&zIn[i]), &zIn[i]);
drh9f18f742015-04-25 00:20:15 +0000609 if( verboseFlag ){
610 printf("%.*s\n", (int)(z-&zIn[i]), &zIn[i]);
611 fflush(stdout);
612 }
drhf34e9aa2015-04-20 12:50:13 +0000613 i += (int)(z-&zIn[i]);
drh1cbb7fa2015-04-24 13:00:59 +0000614 multiTest = 1;
drhf34e9aa2015-04-20 12:50:13 +0000615 }
616 }
617 for(iNext=i; iNext<nIn && strncmp(&zIn[iNext],"/****<",6)!=0; iNext++){}
drh875bafa2015-04-24 14:47:59 +0000618 if( zDataOut ){
619 sqlite3_bind_blob(pStmt, 1, &zIn[i], iNext-i, SQLITE_STATIC);
620 rc = sqlite3_step(pStmt);
621 if( rc!=SQLITE_DONE ) abendError("%s", sqlite3_errmsg(dataDb));
622 sqlite3_reset(pStmt);
623 continue;
624 }
drh3fb2cc12015-04-22 11:16:34 +0000625 cSaved = zIn[iNext];
626 zIn[iNext] = 0;
drh0ba51082015-04-22 13:16:46 +0000627 if( zCkGlob && sqlite3_strglob(zCkGlob,&zIn[i])!=0 ){
drh3fb2cc12015-04-22 11:16:34 +0000628 zIn[iNext] = cSaved;
629 continue;
630 }
drh9985dab2015-04-20 22:36:49 +0000631 zSql = &zIn[i];
drh1cbb7fa2015-04-24 13:00:59 +0000632 if( verboseFlag ){
633 printf("INPUT (offset: %d, size: %d): [%s]\n",
634 i, (int)strlen(&zIn[i]), &zIn[i]);
drh9f18f742015-04-25 00:20:15 +0000635 fflush(stdout);
drh1cbb7fa2015-04-24 13:00:59 +0000636 }else if( multiTest && !quietFlag ){
drh048810b2015-04-24 23:45:23 +0000637 int pct = oomFlag ? 100*iNext/nIn : ((10*iNext)/nIn)*10;
drh1cbb7fa2015-04-24 13:00:59 +0000638 if( pct!=lastPct ){
drhe1a71a52015-04-24 16:09:12 +0000639 if( lastPct<0 ) printf("fuzz test:");
drh048810b2015-04-24 23:45:23 +0000640 printf(" %d%%", pct);
drh1cbb7fa2015-04-24 13:00:59 +0000641 fflush(stdout);
642 lastPct = pct;
643 }
644 }
drh9985dab2015-04-20 22:36:49 +0000645 switch( iMode ){
646 case FZMODE_Glob:
647 zSql = zToFree = sqlite3_mprintf("SELECT glob(%s);", zSql);
648 break;
649 case FZMODE_Printf:
650 zSql = zToFree = sqlite3_mprintf("SELECT printf(%s);", zSql);
651 break;
652 case FZMODE_Strftime:
653 zSql = zToFree = sqlite3_mprintf("SELECT strftime(%s);", zSql);
654 break;
655 }
drh048810b2015-04-24 23:45:23 +0000656 if( oomFlag ){
657 oomCnt = g.iOomCntdown = 1;
658 g.nOomFault = 0;
659 g.bOomOnce = 1;
drh9f18f742015-04-25 00:20:15 +0000660 if( verboseFlag ){
661 printf("Once.%d\n", oomCnt);
662 fflush(stdout);
663 }
drh048810b2015-04-24 23:45:23 +0000664 }else{
665 oomCnt = 0;
666 }
667 do{
668 rc = sqlite3_open_v2(
669 "main.db", &db,
670 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY,
671 0);
672 if( rc!=SQLITE_OK ){
673 abendError("Unable to open the in-memory database");
674 }
675 if( pLook ){
676 rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, pLook, szLook, nLook);
677 if( rc!=SQLITE_OK ) abendError("lookaside configuration filed: %d", rc);
678 }
679 if( zInitDb ){
680 sqlite3_backup *pBackup;
681 pBackup = sqlite3_backup_init(db, "main", dbInit, "main");
682 rc = sqlite3_backup_step(pBackup, -1);
683 if( rc!=SQLITE_DONE ){
684 abendError("attempt to initialize the in-memory database failed (rc=%d)",
685 rc);
686 }
687 sqlite3_backup_finish(pBackup);
688 }
689 #ifndef SQLITE_OMIT_TRACE
drh0ee751f2015-04-25 11:19:51 +0000690 sqlite3_trace(db, verboseFlag ? traceCallback : traceNoop, 0);
drh048810b2015-04-24 23:45:23 +0000691 #endif
692 sqlite3_create_function(db, "eval", 1, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0);
693 sqlite3_create_function(db, "eval", 2, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0);
694 sqlite3_limit(db, SQLITE_LIMIT_LENGTH, 1000000);
695 if( zEncoding ) sqlexec(db, "PRAGMA encoding=%s", zEncoding);
696 if( pageSize ) sqlexec(db, "PRAGMA pagesize=%d", pageSize);
697 if( doAutovac ) sqlexec(db, "PRAGMA auto_vacuum=FULL");
698 g.bOomEnable = 1;
699 if( verboseFlag ){
700 zErrMsg = 0;
701 rc = sqlite3_exec(db, zSql, execCallback, 0, &zErrMsg);
702 if( zErrMsg ){
703 sqlite3_snprintf(sizeof(zErrBuf),zErrBuf,"%z", zErrMsg);
704 zErrMsg = 0;
705 }
706 }else {
707 rc = sqlite3_exec(db, zSql, execNoop, 0, 0);
708 }
709 g.bOomEnable = 0;
710 rc = sqlite3_close(db);
711 if( rc ){
712 abendError("sqlite3_close() failed with rc=%d", rc);
713 }
714 if( sqlite3_memory_used()>0 ){
715 abendError("memory in use after close: %lld bytes", sqlite3_memory_used());
716 }
717 if( oomFlag ){
718 if( g.nOomFault==0 || oomCnt>2000 ){
719 if( g.bOomOnce ){
720 oomCnt = g.iOomCntdown = 1;
721 g.bOomOnce = 0;
722 }else{
723 oomCnt = 0;
724 }
725 }else{
726 g.iOomCntdown = ++oomCnt;
727 g.nOomFault = 0;
728 }
729 if( oomCnt ){
730 if( verboseFlag ){
731 printf("%s.%d\n", g.bOomOnce ? "Once" : "Multi", oomCnt);
drh9f18f742015-04-25 00:20:15 +0000732 fflush(stdout);
drh048810b2015-04-24 23:45:23 +0000733 }
734 nTest++;
735 }
736 }
737 }while( oomCnt>0 );
drh9985dab2015-04-20 22:36:49 +0000738 if( zToFree ){
739 sqlite3_free(zToFree);
740 zToFree = 0;
741 }
drhf34e9aa2015-04-20 12:50:13 +0000742 zIn[iNext] = cSaved;
drh1cbb7fa2015-04-24 13:00:59 +0000743 if( verboseFlag ){
744 printf("RESULT-CODE: %d\n", rc);
745 if( zErrMsg ){
drh048810b2015-04-24 23:45:23 +0000746 printf("ERROR-MSG: [%s]\n", zErrBuf);
drh1cbb7fa2015-04-24 13:00:59 +0000747 }
drh9f18f742015-04-25 00:20:15 +0000748 fflush(stdout);
drhf34e9aa2015-04-20 12:50:13 +0000749 }
drh048810b2015-04-24 23:45:23 +0000750 /* Simulate an error if the TEST_FAILURE environment variable is "5" */
751 if( zFailCode ){
752 if( zFailCode[0]=='5' && zFailCode[1]==0 ){
753 abendError("simulated failure");
754 }else if( zFailCode[0]!=0 ){
755 /* If TEST_FAILURE is something other than 5, just exit the test
756 ** early */
757 printf("\nExit early due to TEST_FAILURE being set");
758 break;
drhe1a71a52015-04-24 16:09:12 +0000759 }
760 }
drhf34e9aa2015-04-20 12:50:13 +0000761 }
drhe1a71a52015-04-24 16:09:12 +0000762 if( !verboseFlag && multiTest && !quietFlag ) printf("\n");
drh1cbb7fa2015-04-24 13:00:59 +0000763 if( nTest>1 && !quietFlag ){
drhe1a71a52015-04-24 16:09:12 +0000764 printf("%d fuzz tests with no errors\nSQLite %s %s\n",
drh875bafa2015-04-24 14:47:59 +0000765 nTest, sqlite3_libversion(), sqlite3_sourceid());
766 }
767 if( zDataOut ){
drh875bafa2015-04-24 14:47:59 +0000768 int n = 0;
drhe1a71a52015-04-24 16:09:12 +0000769 FILE *out = fopen(zDataOut, "wb");
drh875bafa2015-04-24 14:47:59 +0000770 if( out==0 ) abendError("cannot open %s for writing", zDataOut);
drhe1a71a52015-04-24 16:09:12 +0000771 if( nHeader>0 ) fwrite(zIn, nHeader, 1, out);
drh875bafa2015-04-24 14:47:59 +0000772 sqlite3_finalize(pStmt);
773 rc = sqlite3_prepare_v2(dataDb, "SELECT sql FROM testcase", -1, &pStmt, 0);
774 if( rc ) abendError("%s", sqlite3_errmsg(dataDb));
775 while( sqlite3_step(pStmt)==SQLITE_ROW ){
776 fprintf(out,"/****<%d>****/", ++n);
777 fwrite(sqlite3_column_blob(pStmt,0),sqlite3_column_bytes(pStmt,0),1,out);
778 }
779 fclose(out);
780 sqlite3_finalize(pStmt);
781 sqlite3_close(dataDb);
drh1cbb7fa2015-04-24 13:00:59 +0000782 }
drhf34e9aa2015-04-20 12:50:13 +0000783 free(zIn);
drh4a74d072015-04-20 18:58:38 +0000784 free(pHeap);
785 free(pLook);
786 free(pScratch);
787 free(pPCache);
drhf34e9aa2015-04-20 12:50:13 +0000788 return 0;
drh268e72f2015-04-17 14:30:49 +0000789}