blob: dbfa77c0fc78662c12aaaae94e9b2561275071fd [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.)
42** Each such SQL comment is printed as it is encountered. A separate
43** in-memory SQLite database is created to run each chunk of SQL. This
44** feature allows the "queue" of AFL to be captured into a single big
45** file using a command like this:
46**
47** (for i in id:*; do echo '|****<'$i'>****|'; cat $i; done) >~/all-queue.txt
48**
49** (Once again, change the "|" to "/") Then all elements of the AFL queue
drh4a74d072015-04-20 18:58:38 +000050** can be run in a single go (for regression testing, for example) by typing:
drhf34e9aa2015-04-20 12:50:13 +000051**
52** fuzzershell -f ~/all-queue.txt >out.txt
53**
54** After running each chunk of SQL, the database connection is closed. The
55** program aborts if the close fails or if there is any unfreed memory after
56** the close.
drh268e72f2015-04-17 14:30:49 +000057*/
58#include <stdio.h>
59#include <stdlib.h>
60#include <string.h>
61#include <stdarg.h>
drh4a74d072015-04-20 18:58:38 +000062#include <ctype.h>
drh268e72f2015-04-17 14:30:49 +000063#include "sqlite3.h"
64
65/*
66** All global variables are gathered into the "g" singleton.
67*/
68struct GlobalVars {
69 const char *zArgv0; /* Name of program */
70} g;
71
72
73
74/*
75** Print an error message and abort in such a way to indicate to the
76** fuzzer that this counts as a crash.
77*/
78static void abendError(const char *zFormat, ...){
79 va_list ap;
80 fprintf(stderr, "%s: ", g.zArgv0);
81 va_start(ap, zFormat);
82 vfprintf(stderr, zFormat, ap);
83 va_end(ap);
84 fprintf(stderr, "\n");
85 abort();
86}
87/*
88** Print an error message and quit, but not in a way that would look
89** like a crash.
90*/
91static void fatalError(const char *zFormat, ...){
92 va_list ap;
93 fprintf(stderr, "%s: ", g.zArgv0);
94 va_start(ap, zFormat);
95 vfprintf(stderr, zFormat, ap);
96 va_end(ap);
97 fprintf(stderr, "\n");
98 exit(1);
99}
100
101/*
drh4a74d072015-04-20 18:58:38 +0000102** Evaluate some SQL. Abort if unable.
103*/
104static void sqlexec(sqlite3 *db, const char *zFormat, ...){
105 va_list ap;
106 char *zSql;
107 char *zErrMsg = 0;
108 int rc;
109 va_start(ap, zFormat);
110 zSql = sqlite3_vmprintf(zFormat, ap);
111 va_end(ap);
112 rc = sqlite3_exec(db, zSql, 0, 0, &zErrMsg);
113 if( rc ) abendError("failed sql [%s]: %s", zSql, zErrMsg);
114 sqlite3_free(zSql);
115}
116
117/*
drh268e72f2015-04-17 14:30:49 +0000118** This callback is invoked by sqlite3_log().
119*/
120static void shellLog(void *pNotUsed, int iErrCode, const char *zMsg){
121 printf("LOG: (%d) %s\n", iErrCode, zMsg);
122}
123
124/*
125** This callback is invoked by sqlite3_exec() to return query results.
126*/
127static int execCallback(void *NotUsed, int argc, char **argv, char **colv){
128 int i;
129 static unsigned cnt = 0;
130 printf("ROW #%u:\n", ++cnt);
131 for(i=0; i<argc; i++){
132 printf(" %s=", colv[i]);
133 if( argv[i] ){
134 printf("[%s]\n", argv[i]);
135 }else{
136 printf("NULL\n");
137 }
138 }
139 return 0;
140}
drh1cbb7fa2015-04-24 13:00:59 +0000141static int execNoop(void *NotUsed, int argc, char **argv, char **colv){
142 return 0;
143}
drh268e72f2015-04-17 14:30:49 +0000144
145/*
146** This callback is invoked by sqlite3_trace() as each SQL statement
147** starts.
148*/
149static void traceCallback(void *NotUsed, const char *zMsg){
150 printf("TRACE: %s\n", zMsg);
151}
152
153/***************************************************************************
154** eval() implementation copied from ../ext/misc/eval.c
155*/
156/*
157** Structure used to accumulate the output
158*/
159struct EvalResult {
160 char *z; /* Accumulated output */
161 const char *zSep; /* Separator */
162 int szSep; /* Size of the separator string */
163 sqlite3_int64 nAlloc; /* Number of bytes allocated for z[] */
164 sqlite3_int64 nUsed; /* Number of bytes of z[] actually used */
165};
166
167/*
168** Callback from sqlite_exec() for the eval() function.
169*/
170static int callback(void *pCtx, int argc, char **argv, char **colnames){
171 struct EvalResult *p = (struct EvalResult*)pCtx;
172 int i;
173 for(i=0; i<argc; i++){
174 const char *z = argv[i] ? argv[i] : "";
175 size_t sz = strlen(z);
176 if( (sqlite3_int64)sz+p->nUsed+p->szSep+1 > p->nAlloc ){
177 char *zNew;
178 p->nAlloc = p->nAlloc*2 + sz + p->szSep + 1;
179 /* Using sqlite3_realloc64() would be better, but it is a recent
180 ** addition and will cause a segfault if loaded by an older version
181 ** of SQLite. */
182 zNew = p->nAlloc<=0x7fffffff ? sqlite3_realloc(p->z, (int)p->nAlloc) : 0;
183 if( zNew==0 ){
184 sqlite3_free(p->z);
185 memset(p, 0, sizeof(*p));
186 return 1;
187 }
188 p->z = zNew;
189 }
190 if( p->nUsed>0 ){
191 memcpy(&p->z[p->nUsed], p->zSep, p->szSep);
192 p->nUsed += p->szSep;
193 }
194 memcpy(&p->z[p->nUsed], z, sz);
195 p->nUsed += sz;
196 }
197 return 0;
198}
199
200/*
201** Implementation of the eval(X) and eval(X,Y) SQL functions.
202**
203** Evaluate the SQL text in X. Return the results, using string
204** Y as the separator. If Y is omitted, use a single space character.
205*/
206static void sqlEvalFunc(
207 sqlite3_context *context,
208 int argc,
209 sqlite3_value **argv
210){
211 const char *zSql;
212 sqlite3 *db;
213 char *zErr = 0;
214 int rc;
215 struct EvalResult x;
216
217 memset(&x, 0, sizeof(x));
218 x.zSep = " ";
219 zSql = (const char*)sqlite3_value_text(argv[0]);
220 if( zSql==0 ) return;
221 if( argc>1 ){
222 x.zSep = (const char*)sqlite3_value_text(argv[1]);
223 if( x.zSep==0 ) return;
224 }
225 x.szSep = (int)strlen(x.zSep);
226 db = sqlite3_context_db_handle(context);
227 rc = sqlite3_exec(db, zSql, callback, &x, &zErr);
228 if( rc!=SQLITE_OK ){
229 sqlite3_result_error(context, zErr, -1);
230 sqlite3_free(zErr);
231 }else if( x.zSep==0 ){
232 sqlite3_result_error_nomem(context);
233 sqlite3_free(x.z);
234 }else{
235 sqlite3_result_text(context, x.z, (int)x.nUsed, sqlite3_free);
236 }
237}
238/* End of the eval() implementation
239******************************************************************************/
240
241/*
242** Print sketchy documentation for this utility program
243*/
244static void showHelp(void){
245 printf("Usage: %s [options]\n", g.zArgv0);
246 printf(
247"Read SQL text from standard input and evaluate it.\n"
248"Options:\n"
drh4a74d072015-04-20 18:58:38 +0000249" --autovacuum Enable AUTOVACUUM mode\n"
drh268e72f2015-04-17 14:30:49 +0000250" -f FILE Read SQL text from FILE instead of standard input\n"
drh4a74d072015-04-20 18:58:38 +0000251" --heap SZ MIN Memory allocator uses SZ bytes & min allocation MIN\n"
drh268e72f2015-04-17 14:30:49 +0000252" --help Show this help text\n"
253" --initdb DBFILE Initialize the in-memory database using template DBFILE\n"
drh4a74d072015-04-20 18:58:38 +0000254" --lookaside N SZ Configure lookaside for N slots of SZ bytes each\n"
255" --pagesize N Set the page size to N\n"
256" --pcache N SZ Configure N pages of pagecache each of size SZ bytes\n"
drh1cbb7fa2015-04-24 13:00:59 +0000257" -q Reduced output\n"
258" --quiet Reduced output\n"
drh4a74d072015-04-20 18:58:38 +0000259" --scratch N SZ Configure scratch memory for N slots of SZ bytes each\n"
260" --utf16be Set text encoding to UTF-16BE\n"
261" --utf16le Set text encoding to UTF-16LE\n"
drh1cbb7fa2015-04-24 13:00:59 +0000262" -v Increased output\n"
263" --verbose Increased output\n"
drh268e72f2015-04-17 14:30:49 +0000264 );
265}
266
drh4a74d072015-04-20 18:58:38 +0000267/*
268** Return the value of a hexadecimal digit. Return -1 if the input
269** is not a hex digit.
270*/
271static int hexDigitValue(char c){
272 if( c>='0' && c<='9' ) return c - '0';
273 if( c>='a' && c<='f' ) return c - 'a' + 10;
274 if( c>='A' && c<='F' ) return c - 'A' + 10;
275 return -1;
276}
277
278/*
279** Interpret zArg as an integer value, possibly with suffixes.
280*/
281static int integerValue(const char *zArg){
282 sqlite3_int64 v = 0;
283 static const struct { char *zSuffix; int iMult; } aMult[] = {
284 { "KiB", 1024 },
285 { "MiB", 1024*1024 },
286 { "GiB", 1024*1024*1024 },
287 { "KB", 1000 },
288 { "MB", 1000000 },
289 { "GB", 1000000000 },
290 { "K", 1000 },
291 { "M", 1000000 },
292 { "G", 1000000000 },
293 };
294 int i;
295 int isNeg = 0;
296 if( zArg[0]=='-' ){
297 isNeg = 1;
298 zArg++;
299 }else if( zArg[0]=='+' ){
300 zArg++;
301 }
302 if( zArg[0]=='0' && zArg[1]=='x' ){
303 int x;
304 zArg += 2;
305 while( (x = hexDigitValue(zArg[0]))>=0 ){
306 v = (v<<4) + x;
307 zArg++;
308 }
309 }else{
310 while( isdigit(zArg[0]) ){
311 v = v*10 + zArg[0] - '0';
312 zArg++;
313 }
314 }
315 for(i=0; i<sizeof(aMult)/sizeof(aMult[0]); i++){
316 if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
317 v *= aMult[i].iMult;
318 break;
319 }
320 }
321 if( v>0x7fffffff ) abendError("parameter too large - max 2147483648");
322 return (int)(isNeg? -v : v);
323}
324
drh9985dab2015-04-20 22:36:49 +0000325/*
326** Various operating modes
327*/
328#define FZMODE_Generic 1
329#define FZMODE_Strftime 2
330#define FZMODE_Printf 3
331#define FZMODE_Glob 4
332
drh268e72f2015-04-17 14:30:49 +0000333
334int main(int argc, char **argv){
335 char *zIn = 0; /* Input text */
336 int nAlloc = 0; /* Number of bytes allocated for zIn[] */
337 int nIn = 0; /* Number of bytes of zIn[] used */
338 size_t got; /* Bytes read from input */
339 FILE *in = stdin; /* Where to read SQL text from */
340 int rc = SQLITE_OK; /* Result codes from API functions */
341 int i; /* Loop counter */
drhf34e9aa2015-04-20 12:50:13 +0000342 int iNext; /* Next block of SQL */
drh268e72f2015-04-17 14:30:49 +0000343 sqlite3 *db; /* Open database */
drhf34e9aa2015-04-20 12:50:13 +0000344 sqlite3 *dbInit = 0; /* On-disk database used to initialize the in-memory db */
drh268e72f2015-04-17 14:30:49 +0000345 const char *zInitDb = 0;/* Name of the initialization database file */
346 char *zErrMsg = 0; /* Error message returned from sqlite3_exec() */
drh4a74d072015-04-20 18:58:38 +0000347 const char *zEncoding = 0; /* --utf16be or --utf16le */
348 int nHeap = 0, mnHeap = 0; /* Heap size from --heap */
349 int nLook = 0, szLook = 0; /* --lookaside configuration */
350 int nPCache = 0, szPCache = 0;/* --pcache configuration */
351 int nScratch = 0, szScratch=0;/* --scratch configuration */
352 int pageSize = 0; /* Desired page size. 0 means default */
353 void *pHeap = 0; /* Allocated heap space */
354 void *pLook = 0; /* Allocated lookaside space */
355 void *pPCache = 0; /* Allocated storage for pcache */
356 void *pScratch = 0; /* Allocated storage for scratch */
357 int doAutovac = 0; /* True for --autovacuum */
drh9985dab2015-04-20 22:36:49 +0000358 char *zSql; /* SQL to run */
359 char *zToFree = 0; /* Call sqlite3_free() on this afte running zSql */
360 int iMode = FZMODE_Generic; /* Operating mode */
drh0ba51082015-04-22 13:16:46 +0000361 const char *zCkGlob = 0; /* Inputs must match this glob */
drh1cbb7fa2015-04-24 13:00:59 +0000362 int verboseFlag = 0; /* --verbose or -v flag */
363 int quietFlag = 0; /* --quiet or -q flag */
364 int nTest = 0; /* Number of test cases run */
365 int multiTest = 0; /* True if there will be multiple test cases */
366 int lastPct = -1; /* Previous percentage done output */
drh4a74d072015-04-20 18:58:38 +0000367
drh268e72f2015-04-17 14:30:49 +0000368
369 g.zArgv0 = argv[0];
370 for(i=1; i<argc; i++){
371 const char *z = argv[i];
372 if( z[0]=='-' ){
373 z++;
374 if( z[0]=='-' ) z++;
drh4a74d072015-04-20 18:58:38 +0000375 if( strcmp(z,"autovacuum")==0 ){
376 doAutovac = 1;
drh268e72f2015-04-17 14:30:49 +0000377 }else
378 if( strcmp(z, "f")==0 && i+1<argc ){
379 if( in!=stdin ) abendError("only one -f allowed");
380 in = fopen(argv[++i],"rb");
381 if( in==0 ) abendError("cannot open input file \"%s\"", argv[i]);
382 }else
drh4a74d072015-04-20 18:58:38 +0000383 if( strcmp(z,"heap")==0 ){
384 if( i>=argc-2 ) abendError("missing arguments on %s\n", argv[i]);
385 nHeap = integerValue(argv[i+1]);
386 mnHeap = integerValue(argv[i+2]);
387 i += 2;
388 }else
389 if( strcmp(z,"help")==0 ){
390 showHelp();
391 return 0;
392 }else
drh268e72f2015-04-17 14:30:49 +0000393 if( strcmp(z, "initdb")==0 && i+1<argc ){
394 if( zInitDb!=0 ) abendError("only one --initdb allowed");
395 zInitDb = argv[++i];
396 }else
drh4a74d072015-04-20 18:58:38 +0000397 if( strcmp(z,"lookaside")==0 ){
398 if( i>=argc-2 ) abendError("missing arguments on %s", argv[i]);
399 nLook = integerValue(argv[i+1]);
400 szLook = integerValue(argv[i+2]);
401 i += 2;
402 }else
drh9985dab2015-04-20 22:36:49 +0000403 if( strcmp(z,"mode")==0 ){
404 if( i>=argc-1 ) abendError("missing argument on %s", argv[i]);
405 z = argv[++i];
406 if( strcmp(z,"generic")==0 ){
407 iMode = FZMODE_Printf;
drh0ba51082015-04-22 13:16:46 +0000408 zCkGlob = 0;
drh9985dab2015-04-20 22:36:49 +0000409 }else if( strcmp(z, "glob")==0 ){
410 iMode = FZMODE_Glob;
drh0ba51082015-04-22 13:16:46 +0000411 zCkGlob = "'*','*'";
drh9985dab2015-04-20 22:36:49 +0000412 }else if( strcmp(z, "printf")==0 ){
413 iMode = FZMODE_Printf;
drh0ba51082015-04-22 13:16:46 +0000414 zCkGlob = "'*',*";
drh9985dab2015-04-20 22:36:49 +0000415 }else if( strcmp(z, "strftime")==0 ){
416 iMode = FZMODE_Strftime;
drh0ba51082015-04-22 13:16:46 +0000417 zCkGlob = "'*',*";
drh9985dab2015-04-20 22:36:49 +0000418 }else{
419 abendError("unknown --mode: %s", z);
420 }
421 }else
drh4a74d072015-04-20 18:58:38 +0000422 if( strcmp(z,"pagesize")==0 ){
423 if( i>=argc-1 ) abendError("missing argument on %s", argv[i]);
424 pageSize = integerValue(argv[++i]);
425 }else
426 if( strcmp(z,"pcache")==0 ){
427 if( i>=argc-2 ) abendError("missing arguments on %s", argv[i]);
428 nPCache = integerValue(argv[i+1]);
429 szPCache = integerValue(argv[i+2]);
430 i += 2;
431 }else
drh1cbb7fa2015-04-24 13:00:59 +0000432 if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){
433 quietFlag = 1;
434 verboseFlag = 0;
435 }else
drh4a74d072015-04-20 18:58:38 +0000436 if( strcmp(z,"scratch")==0 ){
437 if( i>=argc-2 ) abendError("missing arguments on %s", argv[i]);
438 nScratch = integerValue(argv[i+1]);
439 szScratch = integerValue(argv[i+2]);
440 i += 2;
441 }else
442 if( strcmp(z,"utf16le")==0 ){
443 zEncoding = "utf16le";
444 }else
445 if( strcmp(z,"utf16be")==0 ){
446 zEncoding = "utf16be";
447 }else
drh1cbb7fa2015-04-24 13:00:59 +0000448 if( strcmp(z,"verbose")==0 || strcmp(z,"v")==0 ){
449 quietFlag = 0;
450 verboseFlag = 1;
451 }else
drh268e72f2015-04-17 14:30:49 +0000452 {
453 abendError("unknown option: %s", argv[i]);
454 }
455 }else{
456 abendError("unknown argument: %s", argv[i]);
457 }
458 }
drh1cbb7fa2015-04-24 13:00:59 +0000459 if( verboseFlag ) sqlite3_config(SQLITE_CONFIG_LOG, shellLog, 0);
drh4a74d072015-04-20 18:58:38 +0000460 if( nHeap>0 ){
461 pHeap = malloc( nHeap );
462 if( pHeap==0 ) fatalError("cannot allocate %d-byte heap\n", nHeap);
463 rc = sqlite3_config(SQLITE_CONFIG_HEAP, pHeap, nHeap, mnHeap);
464 if( rc ) abendError("heap configuration failed: %d\n", rc);
465 }
466 if( nLook>0 ){
467 sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 0, 0);
468 if( szLook>0 ){
469 pLook = malloc( nLook*szLook );
470 if( pLook==0 ) fatalError("out of memory");
471 }
472 }
473 if( nScratch>0 && szScratch>0 ){
474 pScratch = malloc( nScratch*(sqlite3_int64)szScratch );
475 if( pScratch==0 ) fatalError("cannot allocate %lld-byte scratch",
476 nScratch*(sqlite3_int64)szScratch);
477 rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, pScratch, szScratch, nScratch);
478 if( rc ) abendError("scratch configuration failed: %d\n", rc);
479 }
480 if( nPCache>0 && szPCache>0 ){
481 pPCache = malloc( nPCache*(sqlite3_int64)szPCache );
482 if( pPCache==0 ) fatalError("cannot allocate %lld-byte pcache",
483 nPCache*(sqlite3_int64)szPCache);
484 rc = sqlite3_config(SQLITE_CONFIG_PAGECACHE, pPCache, szPCache, nPCache);
485 if( rc ) abendError("pcache configuration failed: %d", rc);
486 }
drh268e72f2015-04-17 14:30:49 +0000487 while( !feof(in) ){
drhf34e9aa2015-04-20 12:50:13 +0000488 nAlloc += nAlloc+1000;
489 zIn = realloc(zIn, nAlloc);
drh268e72f2015-04-17 14:30:49 +0000490 if( zIn==0 ) fatalError("out of memory");
491 got = fread(zIn+nIn, 1, nAlloc-nIn-1, in);
492 nIn += (int)got;
493 zIn[nIn] = 0;
494 if( got==0 ) break;
495 }
drhf34e9aa2015-04-20 12:50:13 +0000496 if( zInitDb ){
497 rc = sqlite3_open_v2(zInitDb, &dbInit, SQLITE_OPEN_READONLY, 0);
498 if( rc!=SQLITE_OK ){
499 abendError("unable to open initialization database \"%s\"", zInitDb);
500 }
drh268e72f2015-04-17 14:30:49 +0000501 }
drh1cbb7fa2015-04-24 13:00:59 +0000502 for(i=nTest=0; i<nIn; i=iNext, nTest++){
drhf34e9aa2015-04-20 12:50:13 +0000503 char cSaved;
504 if( strncmp(&zIn[i], "/****<",6)==0 ){
505 char *z = strstr(&zIn[i], ">****/");
506 if( z ){
507 z += 6;
drh1cbb7fa2015-04-24 13:00:59 +0000508 if( verboseFlag ) printf("%.*s\n", (int)(z-&zIn[i]), &zIn[i]);
drhf34e9aa2015-04-20 12:50:13 +0000509 i += (int)(z-&zIn[i]);
drh1cbb7fa2015-04-24 13:00:59 +0000510 multiTest = 1;
drhf34e9aa2015-04-20 12:50:13 +0000511 }
512 }
513 for(iNext=i; iNext<nIn && strncmp(&zIn[iNext],"/****<",6)!=0; iNext++){}
drh3fb2cc12015-04-22 11:16:34 +0000514 cSaved = zIn[iNext];
515 zIn[iNext] = 0;
drh0ba51082015-04-22 13:16:46 +0000516 if( zCkGlob && sqlite3_strglob(zCkGlob,&zIn[i])!=0 ){
drh3fb2cc12015-04-22 11:16:34 +0000517 zIn[iNext] = cSaved;
518 continue;
519 }
drhf34e9aa2015-04-20 12:50:13 +0000520 rc = sqlite3_open_v2(
521 "main.db", &db,
522 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY,
523 0);
524 if( rc!=SQLITE_OK ){
525 abendError("Unable to open the in-memory database");
526 }
drh4a74d072015-04-20 18:58:38 +0000527 if( pLook ){
528 rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, pLook, szLook, nLook);
529 if( rc!=SQLITE_OK ) abendError("lookaside configuration filed: %d", rc);
530 }
drhf34e9aa2015-04-20 12:50:13 +0000531 if( zInitDb ){
532 sqlite3_backup *pBackup;
533 pBackup = sqlite3_backup_init(db, "main", dbInit, "main");
534 rc = sqlite3_backup_step(pBackup, -1);
535 if( rc!=SQLITE_DONE ){
536 abendError("attempt to initialize the in-memory database failed (rc=%d)",
537 rc);
538 }
539 sqlite3_backup_finish(pBackup);
540 }
drh1cbb7fa2015-04-24 13:00:59 +0000541 if( verboseFlag ) sqlite3_trace(db, traceCallback, 0);
drhf34e9aa2015-04-20 12:50:13 +0000542 sqlite3_create_function(db, "eval", 1, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0);
543 sqlite3_create_function(db, "eval", 2, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0);
544 sqlite3_limit(db, SQLITE_LIMIT_LENGTH, 1000000);
drh4a74d072015-04-20 18:58:38 +0000545 if( zEncoding ) sqlexec(db, "PRAGMA encoding=%s", zEncoding);
546 if( pageSize ) sqlexec(db, "PRAGMA pagesize=%d", pageSize);
547 if( doAutovac ) sqlexec(db, "PRAGMA auto_vacuum=FULL");
drh9985dab2015-04-20 22:36:49 +0000548 zSql = &zIn[i];
drh1cbb7fa2015-04-24 13:00:59 +0000549 if( verboseFlag ){
550 printf("INPUT (offset: %d, size: %d): [%s]\n",
551 i, (int)strlen(&zIn[i]), &zIn[i]);
552 }else if( multiTest && !quietFlag ){
553 int pct = 100*(i+strlen(zSql))/nIn;
554 if( pct!=lastPct ){
555 printf("%d%%\r", pct);
556 fflush(stdout);
557 lastPct = pct;
558 }
559 }
drh9985dab2015-04-20 22:36:49 +0000560 switch( iMode ){
561 case FZMODE_Glob:
562 zSql = zToFree = sqlite3_mprintf("SELECT glob(%s);", zSql);
563 break;
564 case FZMODE_Printf:
565 zSql = zToFree = sqlite3_mprintf("SELECT printf(%s);", zSql);
566 break;
567 case FZMODE_Strftime:
568 zSql = zToFree = sqlite3_mprintf("SELECT strftime(%s);", zSql);
569 break;
570 }
drh1cbb7fa2015-04-24 13:00:59 +0000571 zErrMsg = 0;
572 rc = sqlite3_exec(db, zSql, verboseFlag ? execCallback : execNoop, 0, &zErrMsg);
drh9985dab2015-04-20 22:36:49 +0000573 if( zToFree ){
574 sqlite3_free(zToFree);
575 zToFree = 0;
576 }
drhf34e9aa2015-04-20 12:50:13 +0000577 zIn[iNext] = cSaved;
drh1cbb7fa2015-04-24 13:00:59 +0000578 if( verboseFlag ){
579 printf("RESULT-CODE: %d\n", rc);
580 if( zErrMsg ){
581 printf("ERROR-MSG: [%s]\n", zErrMsg);
582 }
drhf34e9aa2015-04-20 12:50:13 +0000583 }
drh1cbb7fa2015-04-24 13:00:59 +0000584 sqlite3_free(zErrMsg);
drhf34e9aa2015-04-20 12:50:13 +0000585 rc = sqlite3_close(db);
586 if( rc ){
587 abendError("sqlite3_close() failed with rc=%d", rc);
588 }
589 if( sqlite3_memory_used()>0 ){
590 abendError("memory in use after close: %lld bytes", sqlite3_memory_used());
591 }
592 }
drh1cbb7fa2015-04-24 13:00:59 +0000593 if( nTest>1 && !quietFlag ){
594 printf("%d tests with no errors\n", nTest);
595 }
drhf34e9aa2015-04-20 12:50:13 +0000596 free(zIn);
drh4a74d072015-04-20 18:58:38 +0000597 free(pHeap);
598 free(pLook);
599 free(pScratch);
600 free(pPCache);
drhf34e9aa2015-04-20 12:50:13 +0000601 return 0;
drh268e72f2015-04-17 14:30:49 +0000602}