xref: /sqlite-3.40.0/test/fuzzcheck.c (revision 2cdcc7f0)
13b74d032Sdrh /*
23b74d032Sdrh ** 2015-05-25
33b74d032Sdrh **
43b74d032Sdrh ** The author disclaims copyright to this source code.  In place of
53b74d032Sdrh ** a legal notice, here is a blessing:
63b74d032Sdrh **
73b74d032Sdrh **    May you do good and not evil.
83b74d032Sdrh **    May you find forgiveness for yourself and forgive others.
93b74d032Sdrh **    May you share freely, never taking more than you give.
103b74d032Sdrh **
113b74d032Sdrh *************************************************************************
123b74d032Sdrh **
1300452196Sdrh ** This is a utility program designed to aid running regressions tests on
14a8781d9dSdrh ** the SQLite library using data from external fuzzers.
153b74d032Sdrh **
163b74d032Sdrh ** This program reads content from an SQLite database file with the following
173b74d032Sdrh ** schema:
183b74d032Sdrh **
193b74d032Sdrh **     CREATE TABLE db(
203b74d032Sdrh **       dbid INTEGER PRIMARY KEY, -- database id
213b74d032Sdrh **       dbcontent BLOB            -- database disk file image
223b74d032Sdrh **     );
233b74d032Sdrh **     CREATE TABLE xsql(
243b74d032Sdrh **       sqlid INTEGER PRIMARY KEY,   -- SQL script id
253b74d032Sdrh **       sqltext TEXT                 -- Text of SQL statements to run
263b74d032Sdrh **     );
2700452196Sdrh **     CREATE TABLE IF NOT EXISTS readme(
2800452196Sdrh **       msg TEXT -- Human-readable description of this test collection
2900452196Sdrh **     );
303b74d032Sdrh **
313b74d032Sdrh ** For each database file in the DB table, the SQL text in the XSQL table
3200452196Sdrh ** is run against that database.  All README.MSG values are printed prior
3300452196Sdrh ** to the start of the test (unless the --quiet option is used).  If the
3400452196Sdrh ** DB table is empty, then all entries in XSQL are run against an empty
3500452196Sdrh ** in-memory database.
3600452196Sdrh **
3700452196Sdrh ** This program is looking for crashes, assertion faults, and/or memory leaks.
3800452196Sdrh ** No attempt is made to verify the output.  The assumption is that either all
3900452196Sdrh ** of the database files or all of the SQL statements are malformed inputs,
4000452196Sdrh ** generated by a fuzzer, that need to be checked to make sure they do not
4100452196Sdrh ** present a security risk.
423b74d032Sdrh **
433b74d032Sdrh ** This program also includes some command-line options to help with
4400452196Sdrh ** creation and maintenance of the source content database.  The command
4500452196Sdrh **
4600452196Sdrh **     ./fuzzcheck database.db --load-sql FILE...
4700452196Sdrh **
4800452196Sdrh ** Loads all FILE... arguments into the XSQL table.  The --load-db option
4900452196Sdrh ** works the same but loads the files into the DB table.  The -m option can
5000452196Sdrh ** be used to initialize the README table.  The "database.db" file is created
5100452196Sdrh ** if it does not previously exist.  Example:
5200452196Sdrh **
5300452196Sdrh **     ./fuzzcheck new.db --load-sql *.sql
5400452196Sdrh **     ./fuzzcheck new.db --load-db *.db
5500452196Sdrh **     ./fuzzcheck new.db -m 'New test cases'
5600452196Sdrh **
5700452196Sdrh ** The three commands above will create the "new.db" file and initialize all
5800452196Sdrh ** tables.  Then do "./fuzzcheck new.db" to run the tests.
5900452196Sdrh **
6000452196Sdrh ** DEBUGGING HINTS:
6100452196Sdrh **
6200452196Sdrh ** If fuzzcheck does crash, it can be run in the debugger and the content
6300452196Sdrh ** of the global variable g.zTextName[] will identify the specific XSQL and
6400452196Sdrh ** DB values that were running when the crash occurred.
65a8781d9dSdrh **
660fcf6f01Sdrh ** DBSQLFUZZ: (Added 2020-02-25)
67a8781d9dSdrh **
68a8781d9dSdrh ** The dbsqlfuzz fuzzer includes both a database file and SQL to run against
69a8781d9dSdrh ** that database in its input.  This utility can now process dbsqlfuzz
70a8781d9dSdrh ** input files.  Load such files using the "--load-dbsql FILE ..." command-line
71a8781d9dSdrh ** option.
72a8781d9dSdrh **
73a8781d9dSdrh ** Dbsqlfuzz inputs are ordinary text.  The first part of the file is text
74a8781d9dSdrh ** that describes the content of the database (using a lot of hexadecimal),
75a8781d9dSdrh ** then there is a divider line followed by the SQL to run against the
76a8781d9dSdrh ** database.  Because they are ordinary text, dbsqlfuzz inputs are stored
77a8781d9dSdrh ** in the XSQL table, as if they were ordinary SQL inputs.  The isDbSql()
78a8781d9dSdrh ** function can look at a text string and determine whether or not it is
79a8781d9dSdrh ** a valid dbsqlfuzz input.
803b74d032Sdrh */
813b74d032Sdrh #include <stdio.h>
823b74d032Sdrh #include <stdlib.h>
833b74d032Sdrh #include <string.h>
843b74d032Sdrh #include <stdarg.h>
853b74d032Sdrh #include <ctype.h>
86a47e709eSdrh #include <assert.h>
873b74d032Sdrh #include "sqlite3.h"
8871b65e88Sdrh #include "sqlite3recover.h"
89c56fac74Sdrh #define ISSPACE(X) isspace((unsigned char)(X))
90c56fac74Sdrh #define ISDIGIT(X) isdigit((unsigned char)(X))
91c56fac74Sdrh 
923b74d032Sdrh 
9394701b04Sdrh #ifdef __unix__
9494701b04Sdrh # include <signal.h>
9594701b04Sdrh # include <unistd.h>
9694701b04Sdrh #endif
9794701b04Sdrh 
98ea432ba2Sdrh #include <stddef.h>
99ac8ba26eSmistachkin #if !defined(_MSC_VER)
100ea432ba2Sdrh # include <stdint.h>
101ea432ba2Sdrh #endif
102ac8ba26eSmistachkin 
103ac8ba26eSmistachkin #if defined(_MSC_VER)
104ac8ba26eSmistachkin typedef unsigned char uint8_t;
105ac8ba26eSmistachkin #endif
106ea432ba2Sdrh 
1073b74d032Sdrh /*
1083b74d032Sdrh ** Files in the virtual file system.
1093b74d032Sdrh */
1103b74d032Sdrh typedef struct VFile VFile;
1113b74d032Sdrh struct VFile {
1123b74d032Sdrh   char *zFilename;      /* Filename.  NULL for delete-on-close. From malloc() */
1133b74d032Sdrh   int sz;               /* Size of the file in bytes */
1143b74d032Sdrh   int nRef;             /* Number of references to this file */
1153b74d032Sdrh   unsigned char *a;     /* Content of the file.  From malloc() */
1163b74d032Sdrh };
1173b74d032Sdrh typedef struct VHandle VHandle;
1183b74d032Sdrh struct VHandle {
1193b74d032Sdrh   sqlite3_file base;      /* Base class.  Must be first */
1203b74d032Sdrh   VFile *pVFile;          /* The underlying file */
1213b74d032Sdrh };
1223b74d032Sdrh 
1233b74d032Sdrh /*
1243b74d032Sdrh ** The value of a database file template, or of an SQL script
1253b74d032Sdrh */
1263b74d032Sdrh typedef struct Blob Blob;
1273b74d032Sdrh struct Blob {
1283b74d032Sdrh   Blob *pNext;            /* Next in a list */
1293b74d032Sdrh   int id;                 /* Id of this Blob */
130e5c5f2cfSdrh   int seq;                /* Sequence number */
1313b74d032Sdrh   int sz;                 /* Size of this Blob in bytes */
1323b74d032Sdrh   unsigned char a[1];     /* Blob content.  Extra space allocated as needed. */
1333b74d032Sdrh };
1343b74d032Sdrh 
1353b74d032Sdrh /*
1363b74d032Sdrh ** Maximum number of files in the in-memory virtual filesystem.
1373b74d032Sdrh */
1383b74d032Sdrh #define MX_FILE  10
1393b74d032Sdrh 
1403b74d032Sdrh /*
1413b74d032Sdrh ** Maximum allowed file size
1423b74d032Sdrh */
1433b74d032Sdrh #define MX_FILE_SZ 10000000
1443b74d032Sdrh 
1453b74d032Sdrh /*
1463b74d032Sdrh ** All global variables are gathered into the "g" singleton.
1473b74d032Sdrh */
1483b74d032Sdrh static struct GlobalVars {
1493b74d032Sdrh   const char *zArgv0;              /* Name of program */
150a7648f02Sdrh   const char *zDbFile;             /* Name of database file */
1513b74d032Sdrh   VFile aFile[MX_FILE];            /* The virtual filesystem */
1523b74d032Sdrh   int nDb;                         /* Number of template databases */
1533b74d032Sdrh   Blob *pFirstDb;                  /* Content of first template database */
1543b74d032Sdrh   int nSql;                        /* Number of SQL scripts */
1553b74d032Sdrh   Blob *pFirstSql;                 /* First SQL script */
156beaf514eSdrh   unsigned int uRandom;            /* Seed for the SQLite PRNG */
157e3bf2c8eSdrh   unsigned int nInvariant;         /* Number of invariant checks run */
1583b74d032Sdrh   char zTestName[100];             /* Name of current test */
1593b74d032Sdrh } g;
1603b74d032Sdrh 
1613b74d032Sdrh /*
16271b65e88Sdrh ** Include the external vt02.c module.
1630fab1099Sdrh */
16471b65e88Sdrh extern int sqlite3_vt02_init(sqlite3*,char***,void*);
16571b65e88Sdrh 
1660fab1099Sdrh 
1670fab1099Sdrh /*
1683b74d032Sdrh ** Print an error message and quit.
1693b74d032Sdrh */
fatalError(const char * zFormat,...)1703b74d032Sdrh static void fatalError(const char *zFormat, ...){
1713b74d032Sdrh   va_list ap;
172a7648f02Sdrh   fprintf(stderr, "%s", g.zArgv0);
173a7648f02Sdrh   if( g.zDbFile ) fprintf(stderr, " %s", g.zDbFile);
174a7648f02Sdrh   if( g.zTestName[0] ) fprintf(stderr, " (%s)", g.zTestName);
175a7648f02Sdrh   fprintf(stderr, ": ");
1763b74d032Sdrh   va_start(ap, zFormat);
1773b74d032Sdrh   vfprintf(stderr, zFormat, ap);
1783b74d032Sdrh   va_end(ap);
1793b74d032Sdrh   fprintf(stderr, "\n");
1803b74d032Sdrh   exit(1);
1813b74d032Sdrh }
1823b74d032Sdrh 
1833b74d032Sdrh /*
184a7648f02Sdrh ** signal handler
18594701b04Sdrh */
18694701b04Sdrh #ifdef __unix__
signalHandler(int signum)187a7648f02Sdrh static void signalHandler(int signum){
188a7648f02Sdrh   const char *zSig;
189a7648f02Sdrh   if( signum==SIGABRT ){
190a7648f02Sdrh     zSig = "abort";
191a7648f02Sdrh   }else if( signum==SIGALRM ){
192a7648f02Sdrh     zSig = "timeout";
193a7648f02Sdrh   }else if( signum==SIGSEGV ){
194a7648f02Sdrh     zSig = "segfault";
195a7648f02Sdrh   }else{
196a7648f02Sdrh     zSig = "signal";
197a7648f02Sdrh   }
198a7648f02Sdrh   fatalError(zSig);
19994701b04Sdrh }
20094701b04Sdrh #endif
20194701b04Sdrh 
20294701b04Sdrh /*
20394701b04Sdrh ** Set the an alarm to go off after N seconds.  Disable the alarm
20494701b04Sdrh ** if N==0
20594701b04Sdrh */
setAlarm(int N)20694701b04Sdrh static void setAlarm(int N){
20794701b04Sdrh #ifdef __unix__
20894701b04Sdrh   alarm(N);
20994701b04Sdrh #else
21094701b04Sdrh   (void)N;
21194701b04Sdrh #endif
21294701b04Sdrh }
21394701b04Sdrh 
21478057351Sdrh #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
21594701b04Sdrh /*
216d83e2831Sdrh ** This an SQL progress handler.  After an SQL statement has run for
217d83e2831Sdrh ** many steps, we want to interrupt it.  This guards against infinite
218d83e2831Sdrh ** loops from recursive common table expressions.
219d83e2831Sdrh **
220d83e2831Sdrh ** *pVdbeLimitFlag is true if the --limit-vdbe command-line option is used.
221d83e2831Sdrh ** In that case, hitting the progress handler is a fatal error.
222d83e2831Sdrh */
progressHandler(void * pVdbeLimitFlag)223d83e2831Sdrh static int progressHandler(void *pVdbeLimitFlag){
224d83e2831Sdrh   if( *(int*)pVdbeLimitFlag ) fatalError("too many VDBE cycles");
225d83e2831Sdrh   return 1;
226d83e2831Sdrh }
22778057351Sdrh #endif
228d83e2831Sdrh 
229d83e2831Sdrh /*
2300fcf6f01Sdrh ** Reallocate memory.  Show an error and quit if unable.
2313b74d032Sdrh */
safe_realloc(void * pOld,int szNew)2323b74d032Sdrh static void *safe_realloc(void *pOld, int szNew){
233c5412d53Sdrh   void *pNew = realloc(pOld, szNew<=0 ? 1 : szNew);
2343b74d032Sdrh   if( pNew==0 ) fatalError("unable to realloc for %d bytes", szNew);
2353b74d032Sdrh   return pNew;
2363b74d032Sdrh }
2373b74d032Sdrh 
2383b74d032Sdrh /*
2393b74d032Sdrh ** Initialize the virtual file system.
2403b74d032Sdrh */
formatVfs(void)2413b74d032Sdrh static void formatVfs(void){
2423b74d032Sdrh   int i;
2433b74d032Sdrh   for(i=0; i<MX_FILE; i++){
2443b74d032Sdrh     g.aFile[i].sz = -1;
2453b74d032Sdrh     g.aFile[i].zFilename = 0;
2463b74d032Sdrh     g.aFile[i].a = 0;
2473b74d032Sdrh     g.aFile[i].nRef = 0;
2483b74d032Sdrh   }
2493b74d032Sdrh }
2503b74d032Sdrh 
2513b74d032Sdrh 
2523b74d032Sdrh /*
2533b74d032Sdrh ** Erase all information in the virtual file system.
2543b74d032Sdrh */
reformatVfs(void)2553b74d032Sdrh static void reformatVfs(void){
2563b74d032Sdrh   int i;
2573b74d032Sdrh   for(i=0; i<MX_FILE; i++){
2583b74d032Sdrh     if( g.aFile[i].sz<0 ) continue;
2593b74d032Sdrh     if( g.aFile[i].zFilename ){
2603b74d032Sdrh       free(g.aFile[i].zFilename);
2613b74d032Sdrh       g.aFile[i].zFilename = 0;
2623b74d032Sdrh     }
2633b74d032Sdrh     if( g.aFile[i].nRef>0 ){
2643b74d032Sdrh       fatalError("file %d still open.  nRef=%d", i, g.aFile[i].nRef);
2653b74d032Sdrh     }
2663b74d032Sdrh     g.aFile[i].sz = -1;
2673b74d032Sdrh     free(g.aFile[i].a);
2683b74d032Sdrh     g.aFile[i].a = 0;
2693b74d032Sdrh     g.aFile[i].nRef = 0;
2703b74d032Sdrh   }
2713b74d032Sdrh }
2723b74d032Sdrh 
2733b74d032Sdrh /*
2743b74d032Sdrh ** Find a VFile by name
2753b74d032Sdrh */
findVFile(const char * zName)2763b74d032Sdrh static VFile *findVFile(const char *zName){
2773b74d032Sdrh   int i;
278a9542b1bSdrh   if( zName==0 ) return 0;
2793b74d032Sdrh   for(i=0; i<MX_FILE; i++){
2803b74d032Sdrh     if( g.aFile[i].zFilename==0 ) continue;
2813b74d032Sdrh     if( strcmp(g.aFile[i].zFilename, zName)==0 ) return &g.aFile[i];
2823b74d032Sdrh   }
2833b74d032Sdrh   return 0;
2843b74d032Sdrh }
2853b74d032Sdrh 
2863b74d032Sdrh /*
2873b74d032Sdrh ** Find a VFile by name.  Create it if it does not already exist and
2883b74d032Sdrh ** initialize it to the size and content given.
2893b74d032Sdrh **
2903b74d032Sdrh ** Return NULL only if the filesystem is full.
2913b74d032Sdrh */
createVFile(const char * zName,int sz,unsigned char * pData)2923b74d032Sdrh static VFile *createVFile(const char *zName, int sz, unsigned char *pData){
2933b74d032Sdrh   VFile *pNew = findVFile(zName);
2943b74d032Sdrh   int i;
2953b74d032Sdrh   if( pNew ) return pNew;
2963b74d032Sdrh   for(i=0; i<MX_FILE && g.aFile[i].sz>=0; i++){}
2973b74d032Sdrh   if( i>=MX_FILE ) return 0;
2983b74d032Sdrh   pNew = &g.aFile[i];
299a9542b1bSdrh   if( zName ){
300e683b898Sdrh     int nName = (int)strlen(zName)+1;
301e683b898Sdrh     pNew->zFilename = safe_realloc(0, nName);
302e683b898Sdrh     memcpy(pNew->zFilename, zName, nName);
303a9542b1bSdrh   }else{
304a9542b1bSdrh     pNew->zFilename = 0;
305a9542b1bSdrh   }
3063b74d032Sdrh   pNew->nRef = 0;
3073b74d032Sdrh   pNew->sz = sz;
3083b74d032Sdrh   pNew->a = safe_realloc(0, sz);
3093b74d032Sdrh   if( sz>0 ) memcpy(pNew->a, pData, sz);
3103b74d032Sdrh   return pNew;
3113b74d032Sdrh }
3123b74d032Sdrh 
313075201e5Sdrh /* Return true if the line is all zeros */
allZero(unsigned char * aLine)314075201e5Sdrh static int allZero(unsigned char *aLine){
315075201e5Sdrh   int i;
316075201e5Sdrh   for(i=0; i<16 && aLine[i]==0; i++){}
317075201e5Sdrh   return i==16;
318075201e5Sdrh }
319075201e5Sdrh 
320075201e5Sdrh /*
321075201e5Sdrh ** Render a database and query as text that can be input into
322075201e5Sdrh ** the CLI.
323075201e5Sdrh */
renderDbSqlForCLI(FILE * out,const char * zFile,unsigned char * aDb,int nDb,unsigned char * zSql,int nSql)324075201e5Sdrh static void renderDbSqlForCLI(
325075201e5Sdrh   FILE *out,             /* Write to this file */
326075201e5Sdrh   const char *zFile,     /* Name of the database file */
327075201e5Sdrh   unsigned char *aDb,    /* Database content */
328075201e5Sdrh   int nDb,               /* Number of bytes in aDb[] */
329075201e5Sdrh   unsigned char *zSql,   /* SQL content */
330075201e5Sdrh   int nSql               /* Bytes of SQL */
331075201e5Sdrh ){
332075201e5Sdrh   fprintf(out, ".print ******* %s *******\n", zFile);
333075201e5Sdrh   if( nDb>100 ){
334075201e5Sdrh     int i, j;                   /* Loop counters */
335075201e5Sdrh     int pgsz;                   /* Size of each page */
336075201e5Sdrh     int lastPage = 0;           /* Last page number shown */
337075201e5Sdrh     int iPage;                  /* Current page number */
338075201e5Sdrh     unsigned char *aLine;       /* Single line to display */
339075201e5Sdrh     unsigned char buf[16];      /* Fake line */
340075201e5Sdrh     unsigned char bShow[256];   /* Characters ok to display */
341075201e5Sdrh 
342075201e5Sdrh     memset(bShow, '.', sizeof(bShow));
343075201e5Sdrh     for(i=' '; i<='~'; i++){
344075201e5Sdrh       if( i!='{' && i!='}' && i!='"' && i!='\\' ) bShow[i] = i;
345075201e5Sdrh     }
346075201e5Sdrh     pgsz = (aDb[16]<<8) | aDb[17];
347075201e5Sdrh     if( pgsz==0 ) pgsz = 65536;
348075201e5Sdrh     if( pgsz<512 || (pgsz&(pgsz-1))!=0 ) pgsz = 4096;
349075201e5Sdrh     fprintf(out,".open --hexdb\n");
350075201e5Sdrh     fprintf(out,"| size %d pagesize %d filename %s\n",nDb,pgsz,zFile);
351075201e5Sdrh     for(i=0; i<nDb; i += 16){
352075201e5Sdrh       if( i+16>nDb ){
353075201e5Sdrh         memset(buf, 0, sizeof(buf));
354075201e5Sdrh         memcpy(buf, aDb+i, nDb-i);
355075201e5Sdrh         aLine = buf;
356075201e5Sdrh       }else{
357075201e5Sdrh         aLine = aDb + i;
358075201e5Sdrh       }
359075201e5Sdrh       if( allZero(aLine) ) continue;
360075201e5Sdrh       iPage = i/pgsz + 1;
361075201e5Sdrh       if( lastPage!=iPage ){
362075201e5Sdrh         fprintf(out,"| page %d offset %d\n", iPage, (iPage-1)*pgsz);
363075201e5Sdrh         lastPage = iPage;
364075201e5Sdrh       }
365075201e5Sdrh       fprintf(out,"|  %5d:", i-(iPage-1)*pgsz);
366075201e5Sdrh       for(j=0; j<16; j++) fprintf(out," %02x", aLine[j]);
367075201e5Sdrh       fprintf(out,"   ");
368075201e5Sdrh       for(j=0; j<16; j++){
369075201e5Sdrh         unsigned char c = (unsigned char)aLine[j];
370075201e5Sdrh         fputc( bShow[c], stdout);
371075201e5Sdrh       }
372075201e5Sdrh       fputc('\n', stdout);
373075201e5Sdrh     }
374075201e5Sdrh     fprintf(out,"| end %s\n", zFile);
375075201e5Sdrh   }else{
376075201e5Sdrh     fprintf(out,".open :memory:\n");
377075201e5Sdrh   }
378075201e5Sdrh   fprintf(out,".testctrl prng_seed 1 db\n");
379075201e5Sdrh   fprintf(out,".testctrl internal_functions\n");
380075201e5Sdrh   fprintf(out,"%.*s", nSql, zSql);
381075201e5Sdrh   if( nSql>0 && zSql[nSql-1]!='\n' ) fprintf(out, "\n");
382075201e5Sdrh }
383075201e5Sdrh 
38448b4bf26Sdrh /*
38548b4bf26Sdrh ** Read the complete content of a file into memory.  Add a 0x00 terminator
38648b4bf26Sdrh ** and return a pointer to the result.
38748b4bf26Sdrh **
38848b4bf26Sdrh ** The file content is held in memory obtained from sqlite_malloc64() which
38948b4bf26Sdrh ** should be freed by the caller.
39048b4bf26Sdrh */
readFile(const char * zFilename,long * sz)39148b4bf26Sdrh static char *readFile(const char *zFilename, long *sz){
39248b4bf26Sdrh   FILE *in;
39348b4bf26Sdrh   long nIn;
39448b4bf26Sdrh   unsigned char *pBuf;
39548b4bf26Sdrh 
39648b4bf26Sdrh   *sz = 0;
39748b4bf26Sdrh   if( zFilename==0 ) return 0;
39848b4bf26Sdrh   in = fopen(zFilename, "rb");
39948b4bf26Sdrh   if( in==0 ) return 0;
40048b4bf26Sdrh   fseek(in, 0, SEEK_END);
40148b4bf26Sdrh   *sz = nIn = ftell(in);
40248b4bf26Sdrh   rewind(in);
40348b4bf26Sdrh   pBuf = sqlite3_malloc64( nIn+1 );
40448b4bf26Sdrh   if( pBuf && 1==fread(pBuf, nIn, 1, in) ){
40548b4bf26Sdrh     pBuf[nIn] = 0;
40648b4bf26Sdrh     fclose(in);
407075201e5Sdrh     return (char*)pBuf;
40848b4bf26Sdrh   }
40948b4bf26Sdrh   sqlite3_free(pBuf);
41048b4bf26Sdrh   *sz = 0;
41148b4bf26Sdrh   fclose(in);
41248b4bf26Sdrh   return 0;
41348b4bf26Sdrh }
41448b4bf26Sdrh 
4153b74d032Sdrh 
4163b74d032Sdrh /*
4173b74d032Sdrh ** Implementation of the "readfile(X)" SQL function.  The entire content
4183b74d032Sdrh ** of the file named X is read and returned as a BLOB.  NULL is returned
4193b74d032Sdrh ** if the file does not exist or is unreadable.
4203b74d032Sdrh */
readfileFunc(sqlite3_context * context,int argc,sqlite3_value ** argv)4213b74d032Sdrh static void readfileFunc(
4223b74d032Sdrh   sqlite3_context *context,
4233b74d032Sdrh   int argc,
4243b74d032Sdrh   sqlite3_value **argv
4253b74d032Sdrh ){
4263b74d032Sdrh   long nIn;
4273b74d032Sdrh   void *pBuf;
42848b4bf26Sdrh   const char *zName = (const char*)sqlite3_value_text(argv[0]);
4293b74d032Sdrh 
4303b74d032Sdrh   if( zName==0 ) return;
43148b4bf26Sdrh   pBuf = readFile(zName, &nIn);
43248b4bf26Sdrh   if( pBuf ){
4333b74d032Sdrh     sqlite3_result_blob(context, pBuf, nIn, sqlite3_free);
4343b74d032Sdrh   }
4353b74d032Sdrh }
4363b74d032Sdrh 
4373b74d032Sdrh /*
438a8781d9dSdrh ** Implementation of the "readtextfile(X)" SQL function.  The text content
439a8781d9dSdrh ** of the file named X through the end of the file or to the first \000
440a8781d9dSdrh ** character, whichever comes first, is read and returned as TEXT.  NULL
441a8781d9dSdrh ** is returned if the file does not exist or is unreadable.
442a8781d9dSdrh */
readtextfileFunc(sqlite3_context * context,int argc,sqlite3_value ** argv)443a8781d9dSdrh static void readtextfileFunc(
444a8781d9dSdrh   sqlite3_context *context,
445a8781d9dSdrh   int argc,
446a8781d9dSdrh   sqlite3_value **argv
447a8781d9dSdrh ){
448a8781d9dSdrh   const char *zName;
449a8781d9dSdrh   FILE *in;
450a8781d9dSdrh   long nIn;
451a8781d9dSdrh   char *pBuf;
452a8781d9dSdrh 
453a8781d9dSdrh   zName = (const char*)sqlite3_value_text(argv[0]);
454a8781d9dSdrh   if( zName==0 ) return;
455a8781d9dSdrh   in = fopen(zName, "rb");
456a8781d9dSdrh   if( in==0 ) return;
457a8781d9dSdrh   fseek(in, 0, SEEK_END);
458a8781d9dSdrh   nIn = ftell(in);
459a8781d9dSdrh   rewind(in);
460a8781d9dSdrh   pBuf = sqlite3_malloc64( nIn+1 );
461a8781d9dSdrh   if( pBuf && 1==fread(pBuf, nIn, 1, in) ){
462a8781d9dSdrh     pBuf[nIn] = 0;
463a8781d9dSdrh     sqlite3_result_text(context, pBuf, -1, sqlite3_free);
464a8781d9dSdrh   }else{
465a8781d9dSdrh     sqlite3_free(pBuf);
466a8781d9dSdrh   }
467a8781d9dSdrh   fclose(in);
468a8781d9dSdrh }
469a8781d9dSdrh 
470a8781d9dSdrh /*
47140e0e0dbSdrh ** Implementation of the "writefile(X,Y)" SQL function.  The argument Y
47240e0e0dbSdrh ** is written into file X.  The number of bytes written is returned.  Or
47340e0e0dbSdrh ** NULL is returned if something goes wrong, such as being unable to open
47440e0e0dbSdrh ** file X for writing.
47540e0e0dbSdrh */
writefileFunc(sqlite3_context * context,int argc,sqlite3_value ** argv)47640e0e0dbSdrh static void writefileFunc(
47740e0e0dbSdrh   sqlite3_context *context,
47840e0e0dbSdrh   int argc,
47940e0e0dbSdrh   sqlite3_value **argv
48040e0e0dbSdrh ){
48140e0e0dbSdrh   FILE *out;
48240e0e0dbSdrh   const char *z;
48340e0e0dbSdrh   sqlite3_int64 rc;
48440e0e0dbSdrh   const char *zFile;
48540e0e0dbSdrh 
48640e0e0dbSdrh   (void)argc;
48740e0e0dbSdrh   zFile = (const char*)sqlite3_value_text(argv[0]);
48840e0e0dbSdrh   if( zFile==0 ) return;
48940e0e0dbSdrh   out = fopen(zFile, "wb");
49040e0e0dbSdrh   if( out==0 ) return;
49140e0e0dbSdrh   z = (const char*)sqlite3_value_blob(argv[1]);
49240e0e0dbSdrh   if( z==0 ){
49340e0e0dbSdrh     rc = 0;
49440e0e0dbSdrh   }else{
49540e0e0dbSdrh     rc = fwrite(z, 1, sqlite3_value_bytes(argv[1]), out);
49640e0e0dbSdrh   }
49740e0e0dbSdrh   fclose(out);
49840e0e0dbSdrh   sqlite3_result_int64(context, rc);
49940e0e0dbSdrh }
50040e0e0dbSdrh 
50140e0e0dbSdrh 
50240e0e0dbSdrh /*
5033b74d032Sdrh ** Load a list of Blob objects from the database
5043b74d032Sdrh */
blobListLoadFromDb(sqlite3 * db,const char * zSql,int onlyId,int * pN,Blob ** ppList)5053b74d032Sdrh static void blobListLoadFromDb(
5063b74d032Sdrh   sqlite3 *db,             /* Read from this database */
5073b74d032Sdrh   const char *zSql,        /* Query used to extract the blobs */
508a9542b1bSdrh   int onlyId,              /* Only load where id is this value */
5093b74d032Sdrh   int *pN,                 /* OUT: Write number of blobs loaded here */
5103b74d032Sdrh   Blob **ppList            /* OUT: Write the head of the blob list here */
5113b74d032Sdrh ){
5123b74d032Sdrh   Blob head;
5133b74d032Sdrh   Blob *p;
5143b74d032Sdrh   sqlite3_stmt *pStmt;
5153b74d032Sdrh   int n = 0;
5163b74d032Sdrh   int rc;
517a9542b1bSdrh   char *z2;
5183b74d032Sdrh 
519a9542b1bSdrh   if( onlyId>0 ){
520a9542b1bSdrh     z2 = sqlite3_mprintf("%s WHERE rowid=%d", zSql, onlyId);
521a9542b1bSdrh   }else{
522a9542b1bSdrh     z2 = sqlite3_mprintf("%s", zSql);
523a9542b1bSdrh   }
524a9542b1bSdrh   rc = sqlite3_prepare_v2(db, z2, -1, &pStmt, 0);
525a9542b1bSdrh   sqlite3_free(z2);
5263b74d032Sdrh   if( rc ) fatalError("%s", sqlite3_errmsg(db));
5273b74d032Sdrh   head.pNext = 0;
5283b74d032Sdrh   p = &head;
5293b74d032Sdrh   while( SQLITE_ROW==sqlite3_step(pStmt) ){
5303b74d032Sdrh     int sz = sqlite3_column_bytes(pStmt, 1);
5313b74d032Sdrh     Blob *pNew = safe_realloc(0, sizeof(*pNew)+sz );
5323b74d032Sdrh     pNew->id = sqlite3_column_int(pStmt, 0);
5333b74d032Sdrh     pNew->sz = sz;
534e5c5f2cfSdrh     pNew->seq = n++;
5353b74d032Sdrh     pNew->pNext = 0;
5363b74d032Sdrh     memcpy(pNew->a, sqlite3_column_blob(pStmt,1), sz);
5373b74d032Sdrh     pNew->a[sz] = 0;
5383b74d032Sdrh     p->pNext = pNew;
5393b74d032Sdrh     p = pNew;
5403b74d032Sdrh   }
5413b74d032Sdrh   sqlite3_finalize(pStmt);
5423b74d032Sdrh   *pN = n;
5433b74d032Sdrh   *ppList = head.pNext;
5443b74d032Sdrh }
5453b74d032Sdrh 
5463b74d032Sdrh /*
5473b74d032Sdrh ** Free a list of Blob objects
5483b74d032Sdrh */
blobListFree(Blob * p)5493b74d032Sdrh static void blobListFree(Blob *p){
5503b74d032Sdrh   Blob *pNext;
5513b74d032Sdrh   while( p ){
5523b74d032Sdrh     pNext = p->pNext;
5533b74d032Sdrh     free(p);
5543b74d032Sdrh     p = pNext;
5553b74d032Sdrh   }
5563b74d032Sdrh }
5573b74d032Sdrh 
558237f41abSdrh /* Return the current wall-clock time
559237f41abSdrh **
560237f41abSdrh ** The number of milliseconds since the julian epoch.
561237f41abSdrh ** 1907-01-01 00:00:00  ->  210866716800000
562237f41abSdrh ** 2021-01-01 00:00:00  ->  212476176000000
563237f41abSdrh */
timeOfDay(void)5643b74d032Sdrh static sqlite3_int64 timeOfDay(void){
5653b74d032Sdrh   static sqlite3_vfs *clockVfs = 0;
5663b74d032Sdrh   sqlite3_int64 t;
5678055a3eaSdrh   if( clockVfs==0 ){
5688055a3eaSdrh     clockVfs = sqlite3_vfs_find(0);
5698055a3eaSdrh     if( clockVfs==0 ) return 0;
5708055a3eaSdrh   }
5713b74d032Sdrh   if( clockVfs->iVersion>=1 && clockVfs->xCurrentTimeInt64!=0 ){
5723b74d032Sdrh     clockVfs->xCurrentTimeInt64(clockVfs, &t);
5733b74d032Sdrh   }else{
5743b74d032Sdrh     double r;
5753b74d032Sdrh     clockVfs->xCurrentTime(clockVfs, &r);
5763b74d032Sdrh     t = (sqlite3_int64)(r*86400000.0);
5773b74d032Sdrh   }
5783b74d032Sdrh   return t;
5793b74d032Sdrh }
5803b74d032Sdrh 
581a47e709eSdrh /***************************************************************************
582a47e709eSdrh ** Code to process combined database+SQL scripts generated by the
583a47e709eSdrh ** dbsqlfuzz fuzzer.
584a47e709eSdrh */
585a47e709eSdrh 
586a47e709eSdrh /* An instance of the following object is passed by pointer as the
587a47e709eSdrh ** client data to various callbacks.
588a47e709eSdrh */
589a47e709eSdrh typedef struct FuzzCtx {
590a47e709eSdrh   sqlite3 *db;               /* The database connection */
591a47e709eSdrh   sqlite3_int64 iCutoffTime; /* Stop processing at this time. */
592a47e709eSdrh   sqlite3_int64 iLastCb;     /* Time recorded for previous progress callback */
593a47e709eSdrh   sqlite3_int64 mxInterval;  /* Longest interval between two progress calls */
594a47e709eSdrh   unsigned nCb;              /* Number of progress callbacks */
595a47e709eSdrh   unsigned mxCb;             /* Maximum number of progress callbacks allowed */
596a47e709eSdrh   unsigned execCnt;          /* Number of calls to the sqlite3_exec callback */
597a47e709eSdrh   int timeoutHit;            /* True when reaching a timeout */
598a47e709eSdrh } FuzzCtx;
599a47e709eSdrh 
600a47e709eSdrh /* Verbosity level for the dbsqlfuzz test runner */
601a47e709eSdrh static int eVerbosity = 0;
602a47e709eSdrh 
603a47e709eSdrh /* True to activate PRAGMA vdbe_debug=on */
604a47e709eSdrh static int bVdbeDebug = 0;
605a47e709eSdrh 
606a47e709eSdrh /* Timeout for each fuzzing attempt, in milliseconds */
607ed457037Sdrh static int giTimeout = 10000;   /* Defaults to 10 seconds */
608a47e709eSdrh 
609a47e709eSdrh /* Maximum number of progress handler callbacks */
610a47e709eSdrh static unsigned int mxProgressCb = 2000;
611a47e709eSdrh 
612a47e709eSdrh /* Maximum string length in SQLite */
613a47e709eSdrh static int lengthLimit = 1000000;
614a47e709eSdrh 
615be03cc9fSdrh /* Maximum expression depth */
616be03cc9fSdrh static int depthLimit = 500;
617be03cc9fSdrh 
61831999c5cSdrh /* Limit on the amount of heap memory that can be used */
619a8781d9dSdrh static sqlite3_int64 heapLimit = 100000000;
62031999c5cSdrh 
621a47e709eSdrh /* Maximum byte-code program length in SQLite */
622a47e709eSdrh static int vdbeOpLimit = 25000;
623a47e709eSdrh 
624a47e709eSdrh /* Maximum size of the in-memory database */
625a47e709eSdrh static sqlite3_int64 maxDbSize = 104857600;
62639b3bcf8Sdrh /* OOM simulation parameters */
62739b3bcf8Sdrh static unsigned int oomCounter = 0;    /* Simulate OOM when equals 1 */
62839b3bcf8Sdrh static unsigned int oomRepeat = 0;     /* Number of OOMs in a row */
62939b3bcf8Sdrh static void*(*defaultMalloc)(int) = 0; /* The low-level malloc routine */
63039b3bcf8Sdrh 
63171b65e88Sdrh /* Enable recovery */
63271b65e88Sdrh static int bNoRecover = 0;
63371b65e88Sdrh 
63439b3bcf8Sdrh /* This routine is called when a simulated OOM occurs.  It is broken
63539b3bcf8Sdrh ** out as a separate routine to make it easy to set a breakpoint on
63639b3bcf8Sdrh ** the OOM
63739b3bcf8Sdrh */
oomFault(void)63839b3bcf8Sdrh void oomFault(void){
63939b3bcf8Sdrh   if( eVerbosity ){
64039b3bcf8Sdrh     printf("Simulated OOM fault\n");
64139b3bcf8Sdrh   }
64239b3bcf8Sdrh   if( oomRepeat>0 ){
64339b3bcf8Sdrh     oomRepeat--;
64439b3bcf8Sdrh   }else{
64539b3bcf8Sdrh     oomCounter--;
64639b3bcf8Sdrh   }
64739b3bcf8Sdrh }
64839b3bcf8Sdrh 
64939b3bcf8Sdrh /* This routine is a replacement malloc() that is used to simulate
65039b3bcf8Sdrh ** Out-Of-Memory (OOM) errors for testing purposes.
65139b3bcf8Sdrh */
oomMalloc(int nByte)65239b3bcf8Sdrh static void *oomMalloc(int nByte){
65339b3bcf8Sdrh   if( oomCounter ){
65439b3bcf8Sdrh     if( oomCounter==1 ){
65539b3bcf8Sdrh       oomFault();
65639b3bcf8Sdrh       return 0;
65739b3bcf8Sdrh     }else{
65839b3bcf8Sdrh       oomCounter--;
65939b3bcf8Sdrh     }
66039b3bcf8Sdrh   }
66139b3bcf8Sdrh   return defaultMalloc(nByte);
66239b3bcf8Sdrh }
66339b3bcf8Sdrh 
66439b3bcf8Sdrh /* Register the OOM simulator.  This must occur before any memory
66539b3bcf8Sdrh ** allocations */
registerOomSimulator(void)66639b3bcf8Sdrh static void registerOomSimulator(void){
66739b3bcf8Sdrh   sqlite3_mem_methods mem;
66839b3bcf8Sdrh   sqlite3_shutdown();
66939b3bcf8Sdrh   sqlite3_config(SQLITE_CONFIG_GETMALLOC, &mem);
67039b3bcf8Sdrh   defaultMalloc = mem.xMalloc;
67139b3bcf8Sdrh   mem.xMalloc = oomMalloc;
67239b3bcf8Sdrh   sqlite3_config(SQLITE_CONFIG_MALLOC, &mem);
67339b3bcf8Sdrh }
67439b3bcf8Sdrh 
67539b3bcf8Sdrh /* Turn off any pending OOM simulation */
disableOom(void)67639b3bcf8Sdrh static void disableOom(void){
67739b3bcf8Sdrh   oomCounter = 0;
67839b3bcf8Sdrh   oomRepeat = 0;
67939b3bcf8Sdrh }
680a47e709eSdrh 
681a47e709eSdrh /*
682a47e709eSdrh ** Translate a single byte of Hex into an integer.
683a47e709eSdrh ** This routine only works if h really is a valid hexadecimal
684a47e709eSdrh ** character:  0..9a..fA..F
685a47e709eSdrh */
hexToInt(unsigned int h)686ed457037Sdrh static unsigned char hexToInt(unsigned int h){
687a47e709eSdrh #ifdef SQLITE_EBCDIC
688a47e709eSdrh   h += 9*(1&~(h>>4));   /* EBCDIC */
689a47e709eSdrh #else
690a47e709eSdrh   h += 9*(1&(h>>6));    /* ASCII */
691a47e709eSdrh #endif
692a47e709eSdrh   return h & 0xf;
693a47e709eSdrh }
694a47e709eSdrh 
695a47e709eSdrh /*
696a47e709eSdrh ** The first character of buffer zIn[0..nIn-1] is a '['.  This routine
697a47e709eSdrh ** checked to see if the buffer holds "[NNNN]" or "[+NNNN]" and if it
698a47e709eSdrh ** does it makes corresponding changes to the *pK value and *pI value
699a47e709eSdrh ** and returns true.  If the input buffer does not match the patterns,
700a47e709eSdrh ** no changes are made to either *pK or *pI and this routine returns false.
701a47e709eSdrh */
isOffset(const unsigned char * zIn,int nIn,unsigned int * pK,unsigned int * pI)702a47e709eSdrh static int isOffset(
703a47e709eSdrh   const unsigned char *zIn,  /* Text input */
704a47e709eSdrh   int nIn,                   /* Bytes of input */
705a47e709eSdrh   unsigned int *pK,          /* half-byte cursor to adjust */
706a47e709eSdrh   unsigned int *pI           /* Input index to adjust */
707a47e709eSdrh ){
708a47e709eSdrh   int i;
709a47e709eSdrh   unsigned int k = 0;
710a47e709eSdrh   unsigned char c;
711a47e709eSdrh   for(i=1; i<nIn && (c = zIn[i])!=']'; i++){
712a47e709eSdrh     if( !isxdigit(c) ) return 0;
713a47e709eSdrh     k = k*16 + hexToInt(c);
714a47e709eSdrh   }
715a47e709eSdrh   if( i==nIn ) return 0;
716a47e709eSdrh   *pK = 2*k;
717a47e709eSdrh   *pI += i;
718a47e709eSdrh   return 1;
719a47e709eSdrh }
720a47e709eSdrh 
721a47e709eSdrh /*
722a47e709eSdrh ** Decode the text starting at zIn into a binary database file.
7230fcf6f01Sdrh ** The maximum length of zIn is nIn bytes.  Store the binary database
7240fcf6f01Sdrh ** file in space obtained from sqlite3_malloc().
725a47e709eSdrh **
726a47e709eSdrh ** Return the number of bytes of zIn consumed.  Or return -1 if there
727a47e709eSdrh ** is an error.  One potential error is that the recipe specifies a
728a47e709eSdrh ** database file larger than MX_FILE_SZ bytes.
729a47e709eSdrh **
730a47e709eSdrh ** Abort on an OOM.
731a47e709eSdrh */
decodeDatabase(const unsigned char * zIn,int nIn,unsigned char ** paDecode,int * pnDecode)732a47e709eSdrh static int decodeDatabase(
733a47e709eSdrh   const unsigned char *zIn,      /* Input text to be decoded */
734a47e709eSdrh   int nIn,                       /* Bytes of input text */
735a47e709eSdrh   unsigned char **paDecode,      /* OUT: decoded database file */
736a47e709eSdrh   int *pnDecode                  /* OUT: Size of decoded database */
737a47e709eSdrh ){
738672f07c6Sdrh   unsigned char *a, *aNew;       /* Database under construction */
739a47e709eSdrh   int mx = 0;                    /* Current size of the database */
740a47e709eSdrh   sqlite3_uint64 nAlloc = 4096;  /* Space allocated in a[] */
741a47e709eSdrh   unsigned int i;                /* Next byte of zIn[] to read */
742a47e709eSdrh   unsigned int j;                /* Temporary integer */
743a47e709eSdrh   unsigned int k;                /* half-byte cursor index for output */
744a47e709eSdrh   unsigned int n;                /* Number of bytes of input */
745a47e709eSdrh   unsigned char b = 0;
746a47e709eSdrh   if( nIn<4 ) return -1;
747a47e709eSdrh   n = (unsigned int)nIn;
748ed457037Sdrh   a = sqlite3_malloc64( nAlloc );
749a47e709eSdrh   if( a==0 ){
750a47e709eSdrh     fprintf(stderr, "Out of memory!\n");
751a47e709eSdrh     exit(1);
752a47e709eSdrh   }
753065f3bf4Smistachkin   memset(a, 0, (size_t)nAlloc);
754a47e709eSdrh   for(i=k=0; i<n; i++){
755af638923Sdrh     unsigned char c = (unsigned char)zIn[i];
756a47e709eSdrh     if( isxdigit(c) ){
757a47e709eSdrh       k++;
758a47e709eSdrh       if( k & 1 ){
759a47e709eSdrh         b = hexToInt(c)*16;
760a47e709eSdrh       }else{
761a47e709eSdrh         b += hexToInt(c);
762a47e709eSdrh         j = k/2 - 1;
763a47e709eSdrh         if( j>=nAlloc ){
764a47e709eSdrh           sqlite3_uint64 newSize;
765a47e709eSdrh           if( nAlloc==MX_FILE_SZ || j>=MX_FILE_SZ ){
766a47e709eSdrh             if( eVerbosity ){
767a47e709eSdrh               fprintf(stderr, "Input database too big: max %d bytes\n",
768a47e709eSdrh                       MX_FILE_SZ);
769a47e709eSdrh             }
770a47e709eSdrh             sqlite3_free(a);
771a47e709eSdrh             return -1;
772a47e709eSdrh           }
773a47e709eSdrh           newSize = nAlloc*2;
774a47e709eSdrh           if( newSize<=j ){
775a47e709eSdrh             newSize = (j+4096)&~4095;
776a47e709eSdrh           }
777a47e709eSdrh           if( newSize>MX_FILE_SZ ){
778a47e709eSdrh             if( j>=MX_FILE_SZ ){
779a47e709eSdrh               sqlite3_free(a);
780a47e709eSdrh               return -1;
781a47e709eSdrh             }
782a47e709eSdrh             newSize = MX_FILE_SZ;
783a47e709eSdrh           }
784672f07c6Sdrh           aNew = sqlite3_realloc64( a, newSize );
785672f07c6Sdrh           if( aNew==0 ){
786672f07c6Sdrh             sqlite3_free(a);
787672f07c6Sdrh             return -1;
788a47e709eSdrh           }
789672f07c6Sdrh           a = aNew;
790a47e709eSdrh           assert( newSize > nAlloc );
791065f3bf4Smistachkin           memset(a+nAlloc, 0, (size_t)(newSize - nAlloc));
792a47e709eSdrh           nAlloc = newSize;
793a47e709eSdrh         }
794a47e709eSdrh         if( j>=(unsigned)mx ){
795a47e709eSdrh           mx = (j + 4095)&~4095;
796a47e709eSdrh           if( mx>MX_FILE_SZ ) mx = MX_FILE_SZ;
797a47e709eSdrh         }
798a47e709eSdrh         assert( j<nAlloc );
799a47e709eSdrh         a[j] = b;
800a47e709eSdrh       }
801a47e709eSdrh     }else if( zIn[i]=='[' && i<n-3 && isOffset(zIn+i, nIn-i, &k, &i) ){
802a47e709eSdrh       continue;
803a47e709eSdrh    }else if( zIn[i]=='\n' && i<n-4 && memcmp(zIn+i,"\n--\n",4)==0 ){
804a47e709eSdrh       i += 4;
805a47e709eSdrh       break;
806a47e709eSdrh     }
807a47e709eSdrh   }
808a47e709eSdrh   *pnDecode = mx;
809a47e709eSdrh   *paDecode = a;
810a47e709eSdrh   return i;
811a47e709eSdrh }
812a47e709eSdrh 
813a47e709eSdrh /*
814a47e709eSdrh ** Progress handler callback.
815a47e709eSdrh **
816a47e709eSdrh ** The argument is the cutoff-time after which all processing should
817a47e709eSdrh ** stop.  So return non-zero if the cut-off time is exceeded.
818a47e709eSdrh */
progress_handler(void * pClientData)819a47e709eSdrh static int progress_handler(void *pClientData) {
820a47e709eSdrh   FuzzCtx *p = (FuzzCtx*)pClientData;
821a47e709eSdrh   sqlite3_int64 iNow = timeOfDay();
822a47e709eSdrh   int rc = iNow>=p->iCutoffTime;
823a47e709eSdrh   sqlite3_int64 iDiff = iNow - p->iLastCb;
824237f41abSdrh   /* printf("time-remaining: %lld\n", p->iCutoffTime - iNow); */
825a47e709eSdrh   if( iDiff > p->mxInterval ) p->mxInterval = iDiff;
826a47e709eSdrh   p->nCb++;
827a47e709eSdrh   if( rc==0 && p->mxCb>0 && p->mxCb<=p->nCb ) rc = 1;
828df21659aSdrh   if( rc && !p->timeoutHit && eVerbosity>=2 ){
829a47e709eSdrh     printf("Timeout on progress callback %d\n", p->nCb);
830a47e709eSdrh     fflush(stdout);
831a47e709eSdrh     p->timeoutHit = 1;
832a47e709eSdrh   }
833a47e709eSdrh   return rc;
834a47e709eSdrh }
835a47e709eSdrh 
836a47e709eSdrh /*
837a1f79daeSdrh ** Flag bits set by block_troublesome_sql()
838a1f79daeSdrh */
839a1f79daeSdrh #define BTS_SELECT      0x000001
840a1f79daeSdrh #define BTS_NONSELECT   0x000002
841a1f79daeSdrh #define BTS_BADFUNC     0x000004
84213736999Sdrh #define BTS_BADPRAGMA   0x000008  /* Sticky for rest of the script */
843a1f79daeSdrh 
844a1f79daeSdrh /*
845a47e709eSdrh ** Disallow debugging pragmas such as "PRAGMA vdbe_debug" and
846a47e709eSdrh ** "PRAGMA parser_trace" since they can dramatically increase the
847a47e709eSdrh ** amount of output without actually testing anything useful.
848a47e709eSdrh **
8498df01497Sdrh ** Also block ATTACH if attaching a file from the filesystem.
850a47e709eSdrh */
block_troublesome_sql(void * pClientData,int eCode,const char * zArg1,const char * zArg2,const char * zArg3,const char * zArg4)851a47e709eSdrh static int block_troublesome_sql(
852a1f79daeSdrh   void *pClientData,
853a47e709eSdrh   int eCode,
854a47e709eSdrh   const char *zArg1,
855a47e709eSdrh   const char *zArg2,
856a47e709eSdrh   const char *zArg3,
857a47e709eSdrh   const char *zArg4
858a47e709eSdrh ){
85913736999Sdrh   unsigned int *pBtsFlags = (unsigned int*)pClientData;
86013736999Sdrh 
861a47e709eSdrh   (void)zArg3;
862a47e709eSdrh   (void)zArg4;
863a1f79daeSdrh   switch( eCode ){
864a1f79daeSdrh     case SQLITE_PRAGMA: {
86563e8f03cSdrh       if( sqlite3_stricmp("busy_timeout",zArg1)==0
86681258cc9Sdrh        && (zArg2==0 || strtoll(zArg2,0,0)>100 || strtoll(zArg2,0,10)>100)
86763e8f03cSdrh       ){
86863e8f03cSdrh         return SQLITE_DENY;
86913736999Sdrh       }else if( sqlite3_stricmp("hard_heap_limit", zArg1)==0
87013736999Sdrh               || sqlite3_stricmp("reverse_unordered_selects", zArg1)==0
87113736999Sdrh       ){
87213736999Sdrh         /* BTS_BADPRAGMA is sticky.  A hard_heap_limit or
87313736999Sdrh         ** revert_unordered_selects should inhibit all future attempts
87413736999Sdrh         ** at verifying query invariants */
87513736999Sdrh         *pBtsFlags |= BTS_BADPRAGMA;
87663e8f03cSdrh       }else if( eVerbosity==0 ){
877a47e709eSdrh         if( sqlite3_strnicmp("vdbe_", zArg1, 5)==0
878a47e709eSdrh          || sqlite3_stricmp("parser_trace", zArg1)==0
879a47e709eSdrh          || sqlite3_stricmp("temp_store_directory", zArg1)==0
880a47e709eSdrh         ){
881a47e709eSdrh          return SQLITE_DENY;
882a47e709eSdrh         }
8838df01497Sdrh       }else if( sqlite3_stricmp("oom",zArg1)==0
8848df01497Sdrh               && zArg2!=0 && zArg2[0]!=0 ){
88539b3bcf8Sdrh         oomCounter = atoi(zArg2);
88639b3bcf8Sdrh       }
88713736999Sdrh       *pBtsFlags |= BTS_NONSELECT;
888a1f79daeSdrh       break;
889a1f79daeSdrh     }
890a1f79daeSdrh     case SQLITE_ATTACH: {
891c8f7211dSdrh       /* Deny the ATTACH if it is attaching anything other than an in-memory
892c8f7211dSdrh       ** database. */
89313736999Sdrh       *pBtsFlags |= BTS_NONSELECT;
894be536561Sdrh       if( zArg1==0 ) return SQLITE_DENY;
895c8f7211dSdrh       if( strcmp(zArg1,":memory:")==0 ) return SQLITE_OK;
896c8f7211dSdrh       if( sqlite3_strglob("file:*[?]vfs=memdb", zArg1)==0
897c8f7211dSdrh        && sqlite3_strglob("file:*[^/a-zA-Z0-9_.]*[?]vfs=memdb", zArg1)!=0
898be536561Sdrh       ){
899c8f7211dSdrh         return SQLITE_OK;
900a47e709eSdrh       }
901c8f7211dSdrh       return SQLITE_DENY;
902657a7a66Sdrh     }
903a1f79daeSdrh     case SQLITE_SELECT: {
90413736999Sdrh       *pBtsFlags |= BTS_SELECT;
905a1f79daeSdrh       break;
906a1f79daeSdrh     }
907a1f79daeSdrh     case SQLITE_FUNCTION: {
908a1f79daeSdrh       static const char *azBadFuncs[] = {
90913736999Sdrh         "avg",
91013736999Sdrh         "count",
91113736999Sdrh         "cume_dist",
91236f904f0Sdrh         "current_date",
91336f904f0Sdrh         "current_time",
91436f904f0Sdrh         "current_timestamp",
91536f904f0Sdrh         "date",
91636f904f0Sdrh         "datetime",
91713736999Sdrh         "decimal_sum",
91813736999Sdrh         "dense_rank",
91913736999Sdrh         "first_value",
92013736999Sdrh         "geopoly_group_bbox",
92113736999Sdrh         "group_concat",
922c2beb0d8Sdrh         "implies_nonnull_row",
92313736999Sdrh         "json_group_array",
92413736999Sdrh         "json_group_object",
92536f904f0Sdrh         "julianday",
92613736999Sdrh         "lag",
92713736999Sdrh         "last_value",
92813736999Sdrh         "lead",
92913736999Sdrh         "max",
93013736999Sdrh         "min",
93113736999Sdrh         "nth_value",
93213736999Sdrh         "ntile",
93313736999Sdrh         "percent_rank",
934a1f79daeSdrh         "random",
935a1f79daeSdrh         "randomblob",
93613736999Sdrh         "rank",
93713736999Sdrh         "row_number",
938f26e4513Sdrh         "sqlite_offset",
93936f904f0Sdrh         "strftime",
94013736999Sdrh         "sum",
94136f904f0Sdrh         "time",
94213736999Sdrh         "total",
94336f904f0Sdrh         "unixepoch",
944a1f79daeSdrh       };
945c2beb0d8Sdrh       int first, last;
946c2beb0d8Sdrh       first = 0;
947c2beb0d8Sdrh       last = sizeof(azBadFuncs)/sizeof(azBadFuncs[0]) - 1;
948c2beb0d8Sdrh       do{
949c2beb0d8Sdrh         int mid = (first+last)/2;
950c2beb0d8Sdrh         int c = sqlite3_stricmp(azBadFuncs[mid], zArg2);
951c2beb0d8Sdrh         if( c<0 ){
952c2beb0d8Sdrh           first = mid+1;
953c2beb0d8Sdrh         }else if( c>0 ){
954c2beb0d8Sdrh           last = mid-1;
955c2beb0d8Sdrh         }else{
95613736999Sdrh           *pBtsFlags |= BTS_BADFUNC;
957a1f79daeSdrh           break;
958a1f79daeSdrh         }
959c2beb0d8Sdrh       }while( first<=last );
960a1f79daeSdrh       break;
961a1f79daeSdrh     }
962a1f79daeSdrh     case SQLITE_READ: {
963a1f79daeSdrh       /* Benign */
964a1f79daeSdrh       break;
965a1f79daeSdrh     }
966a1f79daeSdrh     default: {
96713736999Sdrh       *pBtsFlags |= BTS_NONSELECT;
968a1f79daeSdrh     }
969a1f79daeSdrh   }
970a47e709eSdrh   return SQLITE_OK;
971a47e709eSdrh }
972a47e709eSdrh 
973a1f79daeSdrh /* Implementation found in fuzzinvariant.c */
97471b65e88Sdrh extern int fuzz_invariant(
975a1f79daeSdrh   sqlite3 *db,            /* The database connection */
976a1f79daeSdrh   sqlite3_stmt *pStmt,    /* Test statement stopped on an SQLITE_ROW */
977a1f79daeSdrh   int iCnt,               /* Invariant sequence number, starting at 0 */
978a1f79daeSdrh   int iRow,               /* The row number for pStmt */
97963880362Sdrh   int nRow,               /* Total number of output rows */
980e3bf2c8eSdrh   int *pbCorrupt,         /* IN/OUT: Flag indicating a corrupt database file */
981e3bf2c8eSdrh   int eVerbosity          /* How much debugging output */
982a1f79daeSdrh );
983a1f79daeSdrh 
98471b65e88Sdrh /* Implementation of sqlite_dbdata and sqlite_dbptr */
98571b65e88Sdrh extern int sqlite3_dbdata_init(sqlite3*,const char**,void*);
98671b65e88Sdrh 
98771b65e88Sdrh 
98871b65e88Sdrh /*
98971b65e88Sdrh ** This function is used as a callback by the recover extension. Simply
99071b65e88Sdrh ** print the supplied SQL statement to stdout.
99171b65e88Sdrh */
recoverSqlCb(void * pCtx,const char * zSql)99271b65e88Sdrh static int recoverSqlCb(void *pCtx, const char *zSql){
99371b65e88Sdrh   if( eVerbosity>=2 ){
99471b65e88Sdrh     printf("%s\n", zSql);
99571b65e88Sdrh   }
99671b65e88Sdrh   return SQLITE_OK;
99771b65e88Sdrh }
99871b65e88Sdrh 
99971b65e88Sdrh /*
100071b65e88Sdrh ** This function is called to recover data from the database.
100171b65e88Sdrh */
recoverDatabase(sqlite3 * db)100271b65e88Sdrh static int recoverDatabase(sqlite3 *db){
1003*2cdcc7f0Sdrh   int rc;                                 /* Return code from this routine */
1004*2cdcc7f0Sdrh   const char *zLAF = "lost_and_found";    /* Name of "lost_and_found" table */
1005*2cdcc7f0Sdrh   int bFreelist = 1;                      /* True to scan the freelist */
1006*2cdcc7f0Sdrh   int bRowids = 1;                        /* True to restore ROWID values */
1007*2cdcc7f0Sdrh   sqlite3_recover *p;                     /* The recovery object */
100871b65e88Sdrh 
100971b65e88Sdrh   p = sqlite3_recover_init_sql(db, "main", recoverSqlCb, 0);
101071b65e88Sdrh   sqlite3_recover_config(p, SQLITE_RECOVER_LOST_AND_FOUND, (void*)zLAF);
101171b65e88Sdrh   sqlite3_recover_config(p, SQLITE_RECOVER_ROWIDS, (void*)&bRowids);
101271b65e88Sdrh   sqlite3_recover_config(p, SQLITE_RECOVER_FREELIST_CORRUPT,(void*)&bFreelist);
101371b65e88Sdrh   sqlite3_recover_run(p);
101471b65e88Sdrh   if( sqlite3_recover_errcode(p)!=SQLITE_OK ){
101571b65e88Sdrh     const char *zErr = sqlite3_recover_errmsg(p);
101671b65e88Sdrh     int errCode = sqlite3_recover_errcode(p);
101771b65e88Sdrh     if( eVerbosity>0 ){
101871b65e88Sdrh       printf("recovery error: %s (%d)\n", zErr, errCode);
101971b65e88Sdrh     }
102071b65e88Sdrh   }
102171b65e88Sdrh   rc = sqlite3_recover_finish(p);
102271b65e88Sdrh   if( eVerbosity>0 && rc ){
102371b65e88Sdrh      printf("recovery returns error code %d\n", rc);
102471b65e88Sdrh   }
102571b65e88Sdrh   return rc;
102671b65e88Sdrh }
102771b65e88Sdrh 
1028a47e709eSdrh /*
1029a47e709eSdrh ** Run the SQL text
1030a47e709eSdrh */
runDbSql(sqlite3 * db,const char * zSql,unsigned int * pBtsFlags)1031a1f79daeSdrh static int runDbSql(sqlite3 *db, const char *zSql, unsigned int *pBtsFlags){
1032a47e709eSdrh   int rc;
1033a47e709eSdrh   sqlite3_stmt *pStmt;
1034a1f79daeSdrh   int bCorrupt = 0;
1035af638923Sdrh   while( isspace(zSql[0]&0x7f) ) zSql++;
1036a47e709eSdrh   if( zSql[0]==0 ) return SQLITE_OK;
1037df21659aSdrh   if( eVerbosity>=4 ){
1038a47e709eSdrh     printf("RUNNING-SQL: [%s]\n", zSql);
1039a47e709eSdrh     fflush(stdout);
1040a47e709eSdrh   }
104113736999Sdrh   (*pBtsFlags) &= ~BTS_BADPRAGMA;
1042a47e709eSdrh   rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
1043a47e709eSdrh   if( rc==SQLITE_OK ){
1044a1f79daeSdrh     int nRow = 0;
1045a47e709eSdrh     while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
1046a1f79daeSdrh       nRow++;
104763880362Sdrh       if( eVerbosity>=4 ){
1048a47e709eSdrh         int j;
1049a47e709eSdrh         for(j=0; j<sqlite3_column_count(pStmt); j++){
1050a47e709eSdrh           if( j ) printf(",");
1051a47e709eSdrh           switch( sqlite3_column_type(pStmt, j) ){
1052a47e709eSdrh             case SQLITE_NULL: {
1053a47e709eSdrh               printf("NULL");
1054a47e709eSdrh               break;
1055a47e709eSdrh             }
1056a47e709eSdrh             case SQLITE_INTEGER:
1057a47e709eSdrh             case SQLITE_FLOAT: {
1058a47e709eSdrh               printf("%s", sqlite3_column_text(pStmt, j));
1059a47e709eSdrh               break;
1060a47e709eSdrh             }
1061a47e709eSdrh             case SQLITE_BLOB: {
1062a47e709eSdrh               int n = sqlite3_column_bytes(pStmt, j);
1063a47e709eSdrh               int i;
1064a47e709eSdrh               const unsigned char *a;
1065a47e709eSdrh               a = (const unsigned char*)sqlite3_column_blob(pStmt, j);
1066a47e709eSdrh               printf("x'");
1067a47e709eSdrh               for(i=0; i<n; i++){
1068a47e709eSdrh                 printf("%02x", a[i]);
1069a47e709eSdrh               }
1070a47e709eSdrh               printf("'");
1071a47e709eSdrh               break;
1072a47e709eSdrh             }
1073a47e709eSdrh             case SQLITE_TEXT: {
1074a47e709eSdrh               int n = sqlite3_column_bytes(pStmt, j);
1075a47e709eSdrh               int i;
1076a47e709eSdrh               const unsigned char *a;
1077a47e709eSdrh               a = (const unsigned char*)sqlite3_column_blob(pStmt, j);
1078a47e709eSdrh               printf("'");
1079a47e709eSdrh               for(i=0; i<n; i++){
1080a47e709eSdrh                 if( a[i]=='\'' ){
1081a47e709eSdrh                   printf("''");
1082a47e709eSdrh                 }else{
1083a47e709eSdrh                   putchar(a[i]);
1084a47e709eSdrh                 }
1085a47e709eSdrh               }
1086a47e709eSdrh               printf("'");
1087a47e709eSdrh               break;
1088a47e709eSdrh             }
1089a47e709eSdrh           } /* End switch() */
1090a47e709eSdrh         } /* End for() */
1091a47e709eSdrh         printf("\n");
1092a47e709eSdrh         fflush(stdout);
1093df21659aSdrh       } /* End if( eVerbosity>=5 ) */
1094a47e709eSdrh     } /* End while( SQLITE_ROW */
1095c68fb847Sdrh     if( rc==SQLITE_DONE ){
1096c68fb847Sdrh       if( (*pBtsFlags)==BTS_SELECT
1097c68fb847Sdrh        && !sqlite3_stmt_isexplain(pStmt)
1098c68fb847Sdrh        && nRow>0
1099c68fb847Sdrh       ){
110063880362Sdrh         int iRow = 0;
1101c68fb847Sdrh         sqlite3_reset(pStmt);
1102c68fb847Sdrh         while( sqlite3_step(pStmt)==SQLITE_ROW ){
1103c68fb847Sdrh           int iCnt = 0;
110463880362Sdrh           iRow++;
1105c68fb847Sdrh           for(iCnt=0; iCnt<99999; iCnt++){
110663880362Sdrh             rc = fuzz_invariant(db, pStmt, iCnt, iRow, nRow,
110763880362Sdrh                                 &bCorrupt, eVerbosity);
1108c68fb847Sdrh             if( rc==SQLITE_DONE ) break;
1109c68fb847Sdrh             if( rc!=SQLITE_ERROR ) g.nInvariant++;
1110c68fb847Sdrh             if( eVerbosity>0 ){
1111c68fb847Sdrh               if( rc==SQLITE_OK ){
1112c68fb847Sdrh                 printf("invariant-check: ok\n");
1113c68fb847Sdrh               }else if( rc==SQLITE_CORRUPT ){
1114c68fb847Sdrh                 printf("invariant-check: failed due to database corruption\n");
1115c68fb847Sdrh               }
1116c68fb847Sdrh             }
1117c68fb847Sdrh           }
1118c68fb847Sdrh         }
1119c68fb847Sdrh       }
1120c68fb847Sdrh     }else if( eVerbosity>=4 ){
1121a47e709eSdrh       printf("SQL-ERROR: (%d) %s\n", rc, sqlite3_errmsg(db));
1122a47e709eSdrh       fflush(stdout);
1123a47e709eSdrh     }
1124df21659aSdrh   }else if( eVerbosity>=4 ){
1125a47e709eSdrh     printf("SQL-ERROR (%d): %s\n", rc, sqlite3_errmsg(db));
1126a47e709eSdrh     fflush(stdout);
1127a47e709eSdrh   } /* End if( SQLITE_OK ) */
1128a47e709eSdrh   return sqlite3_finalize(pStmt);
1129a47e709eSdrh }
1130a47e709eSdrh 
1131a47e709eSdrh /* Invoke this routine to run a single test case */
runCombinedDbSqlInput(const uint8_t * aData,size_t nByte,int iTimeout,int bScript,int iSqlId)1132075201e5Sdrh int runCombinedDbSqlInput(
1133075201e5Sdrh   const uint8_t *aData,      /* Combined DB+SQL content */
1134075201e5Sdrh   size_t nByte,              /* Size of aData in bytes */
1135075201e5Sdrh   int iTimeout,              /* Use this timeout */
1136075201e5Sdrh   int bScript,               /* If true, just render CLI output */
1137075201e5Sdrh   int iSqlId                 /* SQL identifier */
1138075201e5Sdrh ){
1139a47e709eSdrh   int rc;                    /* SQLite API return value */
1140a47e709eSdrh   int iSql;                  /* Index in aData[] of start of SQL */
1141a47e709eSdrh   unsigned char *aDb = 0;    /* Decoded database content */
1142a47e709eSdrh   int nDb = 0;               /* Size of the decoded database */
1143a47e709eSdrh   int i;                     /* Loop counter */
1144a47e709eSdrh   int j;                     /* Start of current SQL statement */
1145a47e709eSdrh   char *zSql = 0;            /* SQL text to run */
1146a47e709eSdrh   int nSql;                  /* Bytes of SQL text */
1147a47e709eSdrh   FuzzCtx cx;                /* Fuzzing context */
1148a1f79daeSdrh   unsigned int btsFlags = 0; /* Parsing flags */
1149a47e709eSdrh 
1150a47e709eSdrh   if( nByte<10 ) return 0;
1151a47e709eSdrh   if( sqlite3_initialize() ) return 0;
1152a47e709eSdrh   if( sqlite3_memory_used()!=0 ){
1153a47e709eSdrh     int nAlloc = 0;
1154a47e709eSdrh     int nNotUsed = 0;
1155a47e709eSdrh     sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &nAlloc, &nNotUsed, 0);
1156672f07c6Sdrh     fprintf(stderr,"memory leak prior to test start:"
1157672f07c6Sdrh                    " %lld bytes in %d allocations\n",
1158a47e709eSdrh             sqlite3_memory_used(), nAlloc);
1159a47e709eSdrh     exit(1);
1160a47e709eSdrh   }
1161a47e709eSdrh   memset(&cx, 0, sizeof(cx));
1162a47e709eSdrh   iSql = decodeDatabase((unsigned char*)aData, (int)nByte, &aDb, &nDb);
1163a47e709eSdrh   if( iSql<0 ) return 0;
1164ed457037Sdrh   nSql = (int)(nByte - iSql);
1165075201e5Sdrh   if( bScript ){
1166075201e5Sdrh     char zName[100];
1167075201e5Sdrh     sqlite3_snprintf(sizeof(zName),zName,"dbsql%06d.db",iSqlId);
1168075201e5Sdrh     renderDbSqlForCLI(stdout, zName, aDb, nDb,
1169075201e5Sdrh                       (unsigned char*)(aData+iSql), nSql);
1170075201e5Sdrh     sqlite3_free(aDb);
1171075201e5Sdrh     return 0;
1172075201e5Sdrh   }
1173df21659aSdrh   if( eVerbosity>=3 ){
1174a47e709eSdrh     printf(
1175a47e709eSdrh       "****** %d-byte input, %d-byte database, %d-byte script "
1176a47e709eSdrh       "******\n", (int)nByte, nDb, nSql);
1177a47e709eSdrh     fflush(stdout);
1178a47e709eSdrh   }
1179a47e709eSdrh   rc = sqlite3_open(0, &cx.db);
1180672f07c6Sdrh   if( rc ){
1181672f07c6Sdrh     sqlite3_free(aDb);
1182672f07c6Sdrh     return 1;
1183672f07c6Sdrh   }
1184a47e709eSdrh   if( bVdbeDebug ){
1185a47e709eSdrh     sqlite3_exec(cx.db, "PRAGMA vdbe_debug=ON", 0, 0, 0);
1186a47e709eSdrh   }
1187a47e709eSdrh 
1188a47e709eSdrh   /* Invoke the progress handler frequently to check to see if we
1189a47e709eSdrh   ** are taking too long.  The progress handler will return true
1190ed457037Sdrh   ** (which will block further processing) if more than giTimeout seconds have
1191a47e709eSdrh   ** elapsed since the start of the test.
1192a47e709eSdrh   */
1193a47e709eSdrh   cx.iLastCb = timeOfDay();
1194237f41abSdrh   cx.iCutoffTime = cx.iLastCb + (iTimeout<giTimeout ? iTimeout : giTimeout);
1195a47e709eSdrh   cx.mxCb = mxProgressCb;
1196a47e709eSdrh #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
1197a47e709eSdrh   sqlite3_progress_handler(cx.db, 10, progress_handler, (void*)&cx);
1198a47e709eSdrh #endif
1199a47e709eSdrh 
1200a47e709eSdrh   /* Set a limit on the maximum size of a prepared statement, and the
1201a47e709eSdrh   ** maximum length of a string or blob */
1202a47e709eSdrh   if( vdbeOpLimit>0 ){
1203a47e709eSdrh     sqlite3_limit(cx.db, SQLITE_LIMIT_VDBE_OP, vdbeOpLimit);
1204a47e709eSdrh   }
1205a47e709eSdrh   if( lengthLimit>0 ){
1206a47e709eSdrh     sqlite3_limit(cx.db, SQLITE_LIMIT_LENGTH, lengthLimit);
1207a47e709eSdrh   }
1208be03cc9fSdrh   if( depthLimit>0 ){
1209be03cc9fSdrh     sqlite3_limit(cx.db, SQLITE_LIMIT_EXPR_DEPTH, depthLimit);
1210be03cc9fSdrh   }
12114b3282d8Sdrh   sqlite3_limit(cx.db, SQLITE_LIMIT_LIKE_PATTERN_LENGTH, 100);
121231999c5cSdrh   sqlite3_hard_heap_limit64(heapLimit);
1213a47e709eSdrh 
1214a47e709eSdrh   if( nDb>=20 && aDb[18]==2 && aDb[19]==2 ){
1215a47e709eSdrh     aDb[18] = aDb[19] = 1;
1216a47e709eSdrh   }
1217a47e709eSdrh   rc = sqlite3_deserialize(cx.db, "main", aDb, nDb, nDb,
1218a47e709eSdrh           SQLITE_DESERIALIZE_RESIZEABLE |
1219a47e709eSdrh           SQLITE_DESERIALIZE_FREEONCLOSE);
1220a47e709eSdrh   if( rc ){
1221a47e709eSdrh     fprintf(stderr, "sqlite3_deserialize() failed with %d\n", rc);
1222a47e709eSdrh     goto testrun_finished;
1223a47e709eSdrh   }
1224a47e709eSdrh   if( maxDbSize>0 ){
1225a47e709eSdrh     sqlite3_int64 x = maxDbSize;
1226a47e709eSdrh     sqlite3_file_control(cx.db, "main", SQLITE_FCNTL_SIZE_LIMIT, &x);
1227a47e709eSdrh   }
1228a47e709eSdrh 
1229725a9c7fSdrh   /* For high debugging levels, turn on debug mode */
1230725a9c7fSdrh   if( eVerbosity>=5 ){
1231725a9c7fSdrh     sqlite3_exec(cx.db, "PRAGMA vdbe_debug=ON;", 0, 0, 0);
1232725a9c7fSdrh   }
1233725a9c7fSdrh 
1234a47e709eSdrh   /* Block debug pragmas and ATTACH/DETACH.  But wait until after
1235a47e709eSdrh   ** deserialize to do this because deserialize depends on ATTACH */
1236a1f79daeSdrh   sqlite3_set_authorizer(cx.db, block_troublesome_sql, &btsFlags);
1237a47e709eSdrh 
123871b65e88Sdrh   /* Add the vt02 virtual table */
12390fab1099Sdrh   sqlite3_vt02_init(cx.db, 0, 0);
124071b65e88Sdrh 
124171b65e88Sdrh   /* Add support for sqlite_dbdata and sqlite_dbptr virtual tables used
124271b65e88Sdrh   ** by the recovery API */
124371b65e88Sdrh   sqlite3_dbdata_init(cx.db, 0, 0);
12440fab1099Sdrh 
1245a47e709eSdrh   /* Consistent PRNG seed */
1246319deefdSdrh #ifdef SQLITE_TESTCTRL_PRNG_SEED
1247319deefdSdrh   sqlite3_table_column_metadata(cx.db, 0, "x", 0, 0, 0, 0, 0, 0);
1248319deefdSdrh   sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SEED, 1, cx.db);
1249319deefdSdrh #else
1250a47e709eSdrh   sqlite3_randomness(0,0);
1251319deefdSdrh #endif
1252a47e709eSdrh 
125371b65e88Sdrh   /* Run recovery on the initial database, just to make sure recovery
125471b65e88Sdrh   ** works. */
125571b65e88Sdrh   if( !bNoRecover ){
125671b65e88Sdrh     recoverDatabase(cx.db);
125771b65e88Sdrh   }
125871b65e88Sdrh 
1259a47e709eSdrh   zSql = sqlite3_malloc( nSql + 1 );
1260a47e709eSdrh   if( zSql==0 ){
1261a47e709eSdrh     fprintf(stderr, "Out of memory!\n");
1262a47e709eSdrh   }else{
1263a47e709eSdrh     memcpy(zSql, aData+iSql, nSql);
1264a47e709eSdrh     zSql[nSql] = 0;
1265a47e709eSdrh     for(i=j=0; zSql[i]; i++){
1266a47e709eSdrh       if( zSql[i]==';' ){
1267a47e709eSdrh         char cSaved = zSql[i+1];
1268a47e709eSdrh         zSql[i+1] = 0;
1269a47e709eSdrh         if( sqlite3_complete(zSql+j) ){
1270a1f79daeSdrh           rc = runDbSql(cx.db, zSql+j, &btsFlags);
1271a47e709eSdrh           j = i+1;
1272a47e709eSdrh         }
1273a47e709eSdrh         zSql[i+1] = cSaved;
1274a47e709eSdrh         if( rc==SQLITE_INTERRUPT || progress_handler(&cx) ){
1275a47e709eSdrh           goto testrun_finished;
1276a47e709eSdrh         }
1277a47e709eSdrh       }
1278a47e709eSdrh     }
1279a47e709eSdrh     if( j<i ){
1280a1f79daeSdrh       runDbSql(cx.db, zSql+j, &btsFlags);
1281a47e709eSdrh     }
1282a47e709eSdrh   }
1283a47e709eSdrh testrun_finished:
1284a47e709eSdrh   sqlite3_free(zSql);
1285a47e709eSdrh   rc = sqlite3_close(cx.db);
1286a47e709eSdrh   if( rc!=SQLITE_OK ){
1287a47e709eSdrh     fprintf(stdout, "sqlite3_close() returns %d\n", rc);
1288a47e709eSdrh   }
1289075201e5Sdrh   if( eVerbosity>=2 && !bScript ){
1290a47e709eSdrh     fprintf(stdout, "Peak memory usages: %f MB\n",
1291a47e709eSdrh        sqlite3_memory_highwater(1) / 1000000.0);
1292a47e709eSdrh   }
1293a47e709eSdrh   if( sqlite3_memory_used()!=0 ){
1294a47e709eSdrh     int nAlloc = 0;
1295a47e709eSdrh     int nNotUsed = 0;
1296a47e709eSdrh     sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &nAlloc, &nNotUsed, 0);
1297a47e709eSdrh     fprintf(stderr,"Memory leak: %lld bytes in %d allocations\n",
1298a47e709eSdrh             sqlite3_memory_used(), nAlloc);
1299a47e709eSdrh     exit(1);
1300a47e709eSdrh   }
1301319deefdSdrh   sqlite3_hard_heap_limit64(0);
1302319deefdSdrh   sqlite3_soft_heap_limit64(0);
1303a47e709eSdrh   return 0;
1304a47e709eSdrh }
1305a47e709eSdrh 
1306a47e709eSdrh /*
1307a47e709eSdrh ** END of the dbsqlfuzz code
1308a47e709eSdrh ***************************************************************************/
1309a47e709eSdrh 
1310a47e709eSdrh /* Look at a SQL text and try to determine if it begins with a database
1311a47e709eSdrh ** description, such as would be found in a dbsqlfuzz test case.  Return
1312a47e709eSdrh ** true if this does appear to be a dbsqlfuzz test case and false otherwise.
1313a47e709eSdrh */
isDbSql(unsigned char * a,int n)1314a47e709eSdrh static int isDbSql(unsigned char *a, int n){
1315df21659aSdrh   unsigned char buf[12];
1316df21659aSdrh   int i;
1317a47e709eSdrh   if( n>4 && memcmp(a,"\n--\n",4)==0 ) return 1;
1318a47e709eSdrh   while( n>0 && isspace(a[0]) ){ a++; n--; }
1319df21659aSdrh   for(i=0; n>0 && i<8; n--, a++){
1320df21659aSdrh     if( isxdigit(a[0]) ) buf[i++] = a[0];
1321df21659aSdrh   }
1322df21659aSdrh   if( i==8 && memcmp(buf,"53514c69",8)==0 ) return 1;
1323a47e709eSdrh   return 0;
1324a47e709eSdrh }
1325a47e709eSdrh 
1326e5da9356Sdrh /* Implementation of the isdbsql(TEXT) SQL function.
1327e5da9356Sdrh */
isDbSqlFunc(sqlite3_context * context,int argc,sqlite3_value ** argv)1328e5da9356Sdrh static void isDbSqlFunc(
1329e5da9356Sdrh   sqlite3_context *context,
1330e5da9356Sdrh   int argc,
1331e5da9356Sdrh   sqlite3_value **argv
1332e5da9356Sdrh ){
1333e5da9356Sdrh   int n = sqlite3_value_bytes(argv[0]);
1334e5da9356Sdrh   unsigned char *a = (unsigned char*)sqlite3_value_blob(argv[0]);
1335e5da9356Sdrh   sqlite3_result_int(context, a!=0 && n>0 && isDbSql(a,n));
1336e5da9356Sdrh }
1337a47e709eSdrh 
13383b74d032Sdrh /* Methods for the VHandle object
13393b74d032Sdrh */
inmemClose(sqlite3_file * pFile)13403b74d032Sdrh static int inmemClose(sqlite3_file *pFile){
13413b74d032Sdrh   VHandle *p = (VHandle*)pFile;
13423b74d032Sdrh   VFile *pVFile = p->pVFile;
13433b74d032Sdrh   pVFile->nRef--;
13443b74d032Sdrh   if( pVFile->nRef==0 && pVFile->zFilename==0 ){
13453b74d032Sdrh     pVFile->sz = -1;
13463b74d032Sdrh     free(pVFile->a);
13473b74d032Sdrh     pVFile->a = 0;
13483b74d032Sdrh   }
13493b74d032Sdrh   return SQLITE_OK;
13503b74d032Sdrh }
inmemRead(sqlite3_file * pFile,void * pData,int iAmt,sqlite3_int64 iOfst)13513b74d032Sdrh static int inmemRead(
13523b74d032Sdrh   sqlite3_file *pFile,   /* Read from this open file */
13533b74d032Sdrh   void *pData,           /* Store content in this buffer */
13543b74d032Sdrh   int iAmt,              /* Bytes of content */
13553b74d032Sdrh   sqlite3_int64 iOfst    /* Start reading here */
13563b74d032Sdrh ){
13573b74d032Sdrh   VHandle *pHandle = (VHandle*)pFile;
13583b74d032Sdrh   VFile *pVFile = pHandle->pVFile;
13593b74d032Sdrh   if( iOfst<0 || iOfst>=pVFile->sz ){
13603b74d032Sdrh     memset(pData, 0, iAmt);
13613b74d032Sdrh     return SQLITE_IOERR_SHORT_READ;
13623b74d032Sdrh   }
13633b74d032Sdrh   if( iOfst+iAmt>pVFile->sz ){
13643b74d032Sdrh     memset(pData, 0, iAmt);
13651573dc3bSdrh     iAmt = (int)(pVFile->sz - iOfst);
1366e45985b5Sdrh     memcpy(pData, pVFile->a + iOfst, iAmt);
13673b74d032Sdrh     return SQLITE_IOERR_SHORT_READ;
13683b74d032Sdrh   }
1369aca7ea1eSdrh   memcpy(pData, pVFile->a + iOfst, iAmt);
13703b74d032Sdrh   return SQLITE_OK;
13713b74d032Sdrh }
inmemWrite(sqlite3_file * pFile,const void * pData,int iAmt,sqlite3_int64 iOfst)13723b74d032Sdrh static int inmemWrite(
13733b74d032Sdrh   sqlite3_file *pFile,   /* Write to this file */
13743b74d032Sdrh   const void *pData,     /* Content to write */
13753b74d032Sdrh   int iAmt,              /* bytes to write */
13763b74d032Sdrh   sqlite3_int64 iOfst    /* Start writing here */
13773b74d032Sdrh ){
13783b74d032Sdrh   VHandle *pHandle = (VHandle*)pFile;
13793b74d032Sdrh   VFile *pVFile = pHandle->pVFile;
13803b74d032Sdrh   if( iOfst+iAmt > pVFile->sz ){
1381a9542b1bSdrh     if( iOfst+iAmt >= MX_FILE_SZ ){
1382a9542b1bSdrh       return SQLITE_FULL;
1383a9542b1bSdrh     }
13841573dc3bSdrh     pVFile->a = safe_realloc(pVFile->a, (int)(iOfst+iAmt));
1385908aced5Sdrh     if( iOfst > pVFile->sz ){
13861573dc3bSdrh       memset(pVFile->a + pVFile->sz, 0, (int)(iOfst - pVFile->sz));
1387908aced5Sdrh     }
13881573dc3bSdrh     pVFile->sz = (int)(iOfst + iAmt);
13893b74d032Sdrh   }
13903b74d032Sdrh   memcpy(pVFile->a + iOfst, pData, iAmt);
13913b74d032Sdrh   return SQLITE_OK;
13923b74d032Sdrh }
inmemTruncate(sqlite3_file * pFile,sqlite3_int64 iSize)13933b74d032Sdrh static int inmemTruncate(sqlite3_file *pFile, sqlite3_int64 iSize){
13943b74d032Sdrh   VHandle *pHandle = (VHandle*)pFile;
13953b74d032Sdrh   VFile *pVFile = pHandle->pVFile;
13961573dc3bSdrh   if( pVFile->sz>iSize && iSize>=0 ) pVFile->sz = (int)iSize;
13973b74d032Sdrh   return SQLITE_OK;
13983b74d032Sdrh }
inmemSync(sqlite3_file * pFile,int flags)13993b74d032Sdrh static int inmemSync(sqlite3_file *pFile, int flags){
14003b74d032Sdrh   return SQLITE_OK;
14013b74d032Sdrh }
inmemFileSize(sqlite3_file * pFile,sqlite3_int64 * pSize)14023b74d032Sdrh static int inmemFileSize(sqlite3_file *pFile, sqlite3_int64 *pSize){
14033b74d032Sdrh   *pSize = ((VHandle*)pFile)->pVFile->sz;
14043b74d032Sdrh   return SQLITE_OK;
14053b74d032Sdrh }
inmemLock(sqlite3_file * pFile,int type)14063b74d032Sdrh static int inmemLock(sqlite3_file *pFile, int type){
14073b74d032Sdrh   return SQLITE_OK;
14083b74d032Sdrh }
inmemUnlock(sqlite3_file * pFile,int type)14093b74d032Sdrh static int inmemUnlock(sqlite3_file *pFile, int type){
14103b74d032Sdrh   return SQLITE_OK;
14113b74d032Sdrh }
inmemCheckReservedLock(sqlite3_file * pFile,int * pOut)14123b74d032Sdrh static int inmemCheckReservedLock(sqlite3_file *pFile, int *pOut){
14133b74d032Sdrh   *pOut = 0;
14143b74d032Sdrh   return SQLITE_OK;
14153b74d032Sdrh }
inmemFileControl(sqlite3_file * pFile,int op,void * pArg)14163b74d032Sdrh static int inmemFileControl(sqlite3_file *pFile, int op, void *pArg){
14173b74d032Sdrh   return SQLITE_NOTFOUND;
14183b74d032Sdrh }
inmemSectorSize(sqlite3_file * pFile)14193b74d032Sdrh static int inmemSectorSize(sqlite3_file *pFile){
14203b74d032Sdrh   return 512;
14213b74d032Sdrh }
inmemDeviceCharacteristics(sqlite3_file * pFile)14223b74d032Sdrh static int inmemDeviceCharacteristics(sqlite3_file *pFile){
14233b74d032Sdrh   return
14243b74d032Sdrh       SQLITE_IOCAP_SAFE_APPEND |
14253b74d032Sdrh       SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN |
14263b74d032Sdrh       SQLITE_IOCAP_POWERSAFE_OVERWRITE;
14273b74d032Sdrh }
14283b74d032Sdrh 
14293b74d032Sdrh 
14303b74d032Sdrh /* Method table for VHandle
14313b74d032Sdrh */
14323b74d032Sdrh static sqlite3_io_methods VHandleMethods = {
14333b74d032Sdrh   /* iVersion  */    1,
14343b74d032Sdrh   /* xClose    */    inmemClose,
14353b74d032Sdrh   /* xRead     */    inmemRead,
14363b74d032Sdrh   /* xWrite    */    inmemWrite,
14373b74d032Sdrh   /* xTruncate */    inmemTruncate,
14383b74d032Sdrh   /* xSync     */    inmemSync,
14393b74d032Sdrh   /* xFileSize */    inmemFileSize,
14403b74d032Sdrh   /* xLock     */    inmemLock,
14413b74d032Sdrh   /* xUnlock   */    inmemUnlock,
14423b74d032Sdrh   /* xCheck... */    inmemCheckReservedLock,
14433b74d032Sdrh   /* xFileCtrl */    inmemFileControl,
14443b74d032Sdrh   /* xSectorSz */    inmemSectorSize,
14453b74d032Sdrh   /* xDevchar  */    inmemDeviceCharacteristics,
14463b74d032Sdrh   /* xShmMap   */    0,
14473b74d032Sdrh   /* xShmLock  */    0,
14483b74d032Sdrh   /* xShmBarrier */  0,
14493b74d032Sdrh   /* xShmUnmap */    0,
14503b74d032Sdrh   /* xFetch    */    0,
14513b74d032Sdrh   /* xUnfetch  */    0
14523b74d032Sdrh };
14533b74d032Sdrh 
14543b74d032Sdrh /*
14553b74d032Sdrh ** Open a new file in the inmem VFS.  All files are anonymous and are
14563b74d032Sdrh ** delete-on-close.
14573b74d032Sdrh */
inmemOpen(sqlite3_vfs * pVfs,const char * zFilename,sqlite3_file * pFile,int openFlags,int * pOutFlags)14583b74d032Sdrh static int inmemOpen(
14593b74d032Sdrh   sqlite3_vfs *pVfs,
14603b74d032Sdrh   const char *zFilename,
14613b74d032Sdrh   sqlite3_file *pFile,
14623b74d032Sdrh   int openFlags,
14633b74d032Sdrh   int *pOutFlags
14643b74d032Sdrh ){
14653b74d032Sdrh   VFile *pVFile = createVFile(zFilename, 0, (unsigned char*)"");
14663b74d032Sdrh   VHandle *pHandle = (VHandle*)pFile;
1467a9542b1bSdrh   if( pVFile==0 ){
1468a9542b1bSdrh     return SQLITE_FULL;
1469a9542b1bSdrh   }
14703b74d032Sdrh   pHandle->pVFile = pVFile;
14713b74d032Sdrh   pVFile->nRef++;
14723b74d032Sdrh   pFile->pMethods = &VHandleMethods;
14733b74d032Sdrh   if( pOutFlags ) *pOutFlags = openFlags;
14743b74d032Sdrh   return SQLITE_OK;
14753b74d032Sdrh }
14763b74d032Sdrh 
14773b74d032Sdrh /*
14783b74d032Sdrh ** Delete a file by name
14793b74d032Sdrh */
inmemDelete(sqlite3_vfs * pVfs,const char * zFilename,int syncdir)14803b74d032Sdrh static int inmemDelete(
14813b74d032Sdrh   sqlite3_vfs *pVfs,
14823b74d032Sdrh   const char *zFilename,
14833b74d032Sdrh   int syncdir
14843b74d032Sdrh ){
14853b74d032Sdrh   VFile *pVFile = findVFile(zFilename);
14863b74d032Sdrh   if( pVFile==0 ) return SQLITE_OK;
14873b74d032Sdrh   if( pVFile->nRef==0 ){
14883b74d032Sdrh     free(pVFile->zFilename);
14893b74d032Sdrh     pVFile->zFilename = 0;
14903b74d032Sdrh     pVFile->sz = -1;
14913b74d032Sdrh     free(pVFile->a);
14923b74d032Sdrh     pVFile->a = 0;
14933b74d032Sdrh     return SQLITE_OK;
14943b74d032Sdrh   }
14953b74d032Sdrh   return SQLITE_IOERR_DELETE;
14963b74d032Sdrh }
14973b74d032Sdrh 
14983b74d032Sdrh /* Check for the existance of a file
14993b74d032Sdrh */
inmemAccess(sqlite3_vfs * pVfs,const char * zFilename,int flags,int * pResOut)15003b74d032Sdrh static int inmemAccess(
15013b74d032Sdrh   sqlite3_vfs *pVfs,
15023b74d032Sdrh   const char *zFilename,
15033b74d032Sdrh   int flags,
15043b74d032Sdrh   int *pResOut
15053b74d032Sdrh ){
15063b74d032Sdrh   VFile *pVFile = findVFile(zFilename);
15073b74d032Sdrh   *pResOut =  pVFile!=0;
15083b74d032Sdrh   return SQLITE_OK;
15093b74d032Sdrh }
15103b74d032Sdrh 
15113b74d032Sdrh /* Get the canonical pathname for a file
15123b74d032Sdrh */
inmemFullPathname(sqlite3_vfs * pVfs,const char * zFilename,int nOut,char * zOut)15133b74d032Sdrh static int inmemFullPathname(
15143b74d032Sdrh   sqlite3_vfs *pVfs,
15153b74d032Sdrh   const char *zFilename,
15163b74d032Sdrh   int nOut,
15173b74d032Sdrh   char *zOut
15183b74d032Sdrh ){
15193b74d032Sdrh   sqlite3_snprintf(nOut, zOut, "%s", zFilename);
15203b74d032Sdrh   return SQLITE_OK;
15213b74d032Sdrh }
15223b74d032Sdrh 
1523beaf514eSdrh /* Always use the same random see, for repeatability.
1524beaf514eSdrh */
inmemRandomness(sqlite3_vfs * NotUsed,int nBuf,char * zBuf)1525beaf514eSdrh static int inmemRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){
1526beaf514eSdrh   memset(zBuf, 0, nBuf);
1527beaf514eSdrh   memcpy(zBuf, &g.uRandom, nBuf<sizeof(g.uRandom) ? nBuf : sizeof(g.uRandom));
1528beaf514eSdrh   return nBuf;
1529beaf514eSdrh }
1530beaf514eSdrh 
15313b74d032Sdrh /*
15323b74d032Sdrh ** Register the VFS that reads from the g.aFile[] set of files.
15333b74d032Sdrh */
inmemVfsRegister(int makeDefault)1534beaf514eSdrh static void inmemVfsRegister(int makeDefault){
15353b74d032Sdrh   static sqlite3_vfs inmemVfs;
15363b74d032Sdrh   sqlite3_vfs *pDefault = sqlite3_vfs_find(0);
15375337dacbSdrh   inmemVfs.iVersion = 3;
15383b74d032Sdrh   inmemVfs.szOsFile = sizeof(VHandle);
15393b74d032Sdrh   inmemVfs.mxPathname = 200;
15403b74d032Sdrh   inmemVfs.zName = "inmem";
15413b74d032Sdrh   inmemVfs.xOpen = inmemOpen;
15423b74d032Sdrh   inmemVfs.xDelete = inmemDelete;
15433b74d032Sdrh   inmemVfs.xAccess = inmemAccess;
15443b74d032Sdrh   inmemVfs.xFullPathname = inmemFullPathname;
1545beaf514eSdrh   inmemVfs.xRandomness = inmemRandomness;
15463b74d032Sdrh   inmemVfs.xSleep = pDefault->xSleep;
15475337dacbSdrh   inmemVfs.xCurrentTimeInt64 = pDefault->xCurrentTimeInt64;
1548beaf514eSdrh   sqlite3_vfs_register(&inmemVfs, makeDefault);
15493b74d032Sdrh };
15503b74d032Sdrh 
15513b74d032Sdrh /*
1552e5c5f2cfSdrh ** Allowed values for the runFlags parameter to runSql()
1553e5c5f2cfSdrh */
1554e5c5f2cfSdrh #define SQL_TRACE  0x0001     /* Print each SQL statement as it is prepared */
1555e5c5f2cfSdrh #define SQL_OUTPUT 0x0002     /* Show the SQL output */
1556e5c5f2cfSdrh 
1557e5c5f2cfSdrh /*
15583b74d032Sdrh ** Run multiple commands of SQL.  Similar to sqlite3_exec(), but does not
15593b74d032Sdrh ** stop if an error is encountered.
15603b74d032Sdrh */
runSql(sqlite3 * db,const char * zSql,unsigned runFlags)1561e5c5f2cfSdrh static void runSql(sqlite3 *db, const char *zSql, unsigned  runFlags){
15623b74d032Sdrh   const char *zMore;
15633b74d032Sdrh   sqlite3_stmt *pStmt;
15643b74d032Sdrh 
15653b74d032Sdrh   while( zSql && zSql[0] ){
15663b74d032Sdrh     zMore = 0;
15673b74d032Sdrh     pStmt = 0;
15683b74d032Sdrh     sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zMore);
15694ab31475Sdrh     if( zMore==zSql ) break;
1570e5c5f2cfSdrh     if( runFlags & SQL_TRACE ){
15714ab31475Sdrh       const char *z = zSql;
15724ab31475Sdrh       int n;
1573c56fac74Sdrh       while( z<zMore && ISSPACE(z[0]) ) z++;
15744ab31475Sdrh       n = (int)(zMore - z);
1575c56fac74Sdrh       while( n>0 && ISSPACE(z[n-1]) ) n--;
15764ab31475Sdrh       if( n==0 ) break;
15774ab31475Sdrh       if( pStmt==0 ){
15784ab31475Sdrh         printf("TRACE: %.*s (error: %s)\n", n, z, sqlite3_errmsg(db));
15794ab31475Sdrh       }else{
15804ab31475Sdrh         printf("TRACE: %.*s\n", n, z);
15814ab31475Sdrh       }
15824ab31475Sdrh     }
15833b74d032Sdrh     zSql = zMore;
15843b74d032Sdrh     if( pStmt ){
1585e5c5f2cfSdrh       if( (runFlags & SQL_OUTPUT)==0 ){
15864ab31475Sdrh         while( SQLITE_ROW==sqlite3_step(pStmt) ){}
1587e5c5f2cfSdrh       }else{
1588e5c5f2cfSdrh         int nCol = -1;
1589e5c5f2cfSdrh         while( SQLITE_ROW==sqlite3_step(pStmt) ){
1590e5c5f2cfSdrh           int i;
1591e5c5f2cfSdrh           if( nCol<0 ){
1592e5c5f2cfSdrh             nCol = sqlite3_column_count(pStmt);
1593e5c5f2cfSdrh           }else if( nCol>0 ){
1594e5c5f2cfSdrh             printf("--------------------------------------------\n");
1595e5c5f2cfSdrh           }
1596e5c5f2cfSdrh           for(i=0; i<nCol; i++){
1597e5c5f2cfSdrh             int eType = sqlite3_column_type(pStmt,i);
1598e5c5f2cfSdrh             printf("%s = ", sqlite3_column_name(pStmt,i));
1599e5c5f2cfSdrh             switch( eType ){
1600e5c5f2cfSdrh               case SQLITE_NULL: {
1601e5c5f2cfSdrh                 printf("NULL\n");
1602e5c5f2cfSdrh                 break;
1603e5c5f2cfSdrh               }
1604e5c5f2cfSdrh               case SQLITE_INTEGER: {
1605e5c5f2cfSdrh                 printf("INT %s\n", sqlite3_column_text(pStmt,i));
1606e5c5f2cfSdrh                 break;
1607e5c5f2cfSdrh               }
1608e5c5f2cfSdrh               case SQLITE_FLOAT: {
1609e5c5f2cfSdrh                 printf("FLOAT %s\n", sqlite3_column_text(pStmt,i));
1610e5c5f2cfSdrh                 break;
1611e5c5f2cfSdrh               }
1612e5c5f2cfSdrh               case SQLITE_TEXT: {
1613e5c5f2cfSdrh                 printf("TEXT [%s]\n", sqlite3_column_text(pStmt,i));
1614e5c5f2cfSdrh                 break;
1615e5c5f2cfSdrh               }
1616e5c5f2cfSdrh               case SQLITE_BLOB: {
1617e5c5f2cfSdrh                 printf("BLOB (%d bytes)\n", sqlite3_column_bytes(pStmt,i));
1618e5c5f2cfSdrh                 break;
1619e5c5f2cfSdrh               }
1620e5c5f2cfSdrh             }
1621e5c5f2cfSdrh           }
1622e5c5f2cfSdrh         }
1623e5c5f2cfSdrh       }
16243b74d032Sdrh       sqlite3_finalize(pStmt);
16253b74d032Sdrh     }
16263b74d032Sdrh   }
16273b74d032Sdrh }
16283b74d032Sdrh 
1629a9542b1bSdrh /*
16309a645868Sdrh ** Rebuild the database file.
16319a645868Sdrh **
16329a645868Sdrh **    (1)  Remove duplicate entries
16339a645868Sdrh **    (2)  Put all entries in order
16349a645868Sdrh **    (3)  Vacuum
16359a645868Sdrh */
rebuild_database(sqlite3 * db,int dbSqlOnly)1636e5da9356Sdrh static void rebuild_database(sqlite3 *db, int dbSqlOnly){
16379a645868Sdrh   int rc;
1638e5da9356Sdrh   char *zSql;
1639e5da9356Sdrh   zSql = sqlite3_mprintf(
16409a645868Sdrh      "BEGIN;\n"
16419a645868Sdrh      "CREATE TEMP TABLE dbx AS SELECT DISTINCT dbcontent FROM db;\n"
16429a645868Sdrh      "DELETE FROM db;\n"
16435ecf9039Sdrh      "INSERT INTO db(dbid, dbcontent) "
16445ecf9039Sdrh         " SELECT NULL, dbcontent FROM dbx ORDER BY 2;\n"
16459a645868Sdrh      "DROP TABLE dbx;\n"
1646e5da9356Sdrh      "CREATE TEMP TABLE sx AS SELECT DISTINCT sqltext FROM xsql %s;\n"
16479a645868Sdrh      "DELETE FROM xsql;\n"
16485ecf9039Sdrh      "INSERT INTO xsql(sqlid,sqltext) "
16495ecf9039Sdrh         " SELECT NULL, sqltext FROM sx ORDER BY 2;\n"
16509a645868Sdrh      "DROP TABLE sx;\n"
16519a645868Sdrh      "COMMIT;\n"
16529a645868Sdrh      "PRAGMA page_size=1024;\n"
1653e5da9356Sdrh      "VACUUM;\n",
1654e5da9356Sdrh      dbSqlOnly ? " WHERE isdbsql(sqltext)" : ""
1655e5da9356Sdrh   );
1656e5da9356Sdrh   rc = sqlite3_exec(db, zSql, 0, 0, 0);
1657e5da9356Sdrh   sqlite3_free(zSql);
16589a645868Sdrh   if( rc ) fatalError("cannot rebuild: %s", sqlite3_errmsg(db));
16599a645868Sdrh }
16609a645868Sdrh 
16619a645868Sdrh /*
166253e66c3cSdrh ** Return the value of a hexadecimal digit.  Return -1 if the input
166353e66c3cSdrh ** is not a hex digit.
166453e66c3cSdrh */
hexDigitValue(char c)166553e66c3cSdrh static int hexDigitValue(char c){
166653e66c3cSdrh   if( c>='0' && c<='9' ) return c - '0';
166753e66c3cSdrh   if( c>='a' && c<='f' ) return c - 'a' + 10;
166853e66c3cSdrh   if( c>='A' && c<='F' ) return c - 'A' + 10;
166953e66c3cSdrh   return -1;
167053e66c3cSdrh }
167153e66c3cSdrh 
167253e66c3cSdrh /*
167353e66c3cSdrh ** Interpret zArg as an integer value, possibly with suffixes.
167453e66c3cSdrh */
integerValue(const char * zArg)167553e66c3cSdrh static int integerValue(const char *zArg){
167653e66c3cSdrh   sqlite3_int64 v = 0;
167753e66c3cSdrh   static const struct { char *zSuffix; int iMult; } aMult[] = {
167853e66c3cSdrh     { "KiB", 1024 },
167953e66c3cSdrh     { "MiB", 1024*1024 },
168053e66c3cSdrh     { "GiB", 1024*1024*1024 },
168153e66c3cSdrh     { "KB",  1000 },
168253e66c3cSdrh     { "MB",  1000000 },
168353e66c3cSdrh     { "GB",  1000000000 },
168453e66c3cSdrh     { "K",   1000 },
168553e66c3cSdrh     { "M",   1000000 },
168653e66c3cSdrh     { "G",   1000000000 },
168753e66c3cSdrh   };
168853e66c3cSdrh   int i;
168953e66c3cSdrh   int isNeg = 0;
169053e66c3cSdrh   if( zArg[0]=='-' ){
169153e66c3cSdrh     isNeg = 1;
169253e66c3cSdrh     zArg++;
169353e66c3cSdrh   }else if( zArg[0]=='+' ){
169453e66c3cSdrh     zArg++;
169553e66c3cSdrh   }
169653e66c3cSdrh   if( zArg[0]=='0' && zArg[1]=='x' ){
169753e66c3cSdrh     int x;
169853e66c3cSdrh     zArg += 2;
169953e66c3cSdrh     while( (x = hexDigitValue(zArg[0]))>=0 ){
170053e66c3cSdrh       v = (v<<4) + x;
170153e66c3cSdrh       zArg++;
170253e66c3cSdrh     }
170353e66c3cSdrh   }else{
1704c56fac74Sdrh     while( ISDIGIT(zArg[0]) ){
170553e66c3cSdrh       v = v*10 + zArg[0] - '0';
170653e66c3cSdrh       zArg++;
170753e66c3cSdrh     }
170853e66c3cSdrh   }
170953e66c3cSdrh   for(i=0; i<sizeof(aMult)/sizeof(aMult[0]); i++){
171053e66c3cSdrh     if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
171153e66c3cSdrh       v *= aMult[i].iMult;
171253e66c3cSdrh       break;
171353e66c3cSdrh     }
171453e66c3cSdrh   }
171553e66c3cSdrh   if( v>0x7fffffff ) fatalError("parameter too large - max 2147483648");
171653e66c3cSdrh   return (int)(isNeg? -v : v);
171753e66c3cSdrh }
171853e66c3cSdrh 
171953e66c3cSdrh /*
1720725a9c7fSdrh ** Return the number of "v" characters in a string.  Return 0 if there
1721725a9c7fSdrh ** are any characters in the string other than "v".
1722725a9c7fSdrh */
numberOfVChar(const char * z)1723725a9c7fSdrh static int numberOfVChar(const char *z){
1724725a9c7fSdrh   int N = 0;
1725725a9c7fSdrh   while( z[0] && z[0]=='v' ){
1726725a9c7fSdrh     z++;
1727725a9c7fSdrh     N++;
1728725a9c7fSdrh   }
1729725a9c7fSdrh   return z[0]==0 ? N : 0;
1730725a9c7fSdrh }
1731725a9c7fSdrh 
1732725a9c7fSdrh /*
1733a9542b1bSdrh ** Print sketchy documentation for this utility program
1734a9542b1bSdrh */
showHelp(void)1735a9542b1bSdrh static void showHelp(void){
1736a9542b1bSdrh   printf("Usage: %s [options] SOURCE-DB ?ARGS...?\n", g.zArgv0);
1737a9542b1bSdrh   printf(
1738a9542b1bSdrh "Read databases and SQL scripts from SOURCE-DB and execute each script against\n"
1739a9542b1bSdrh "each database, checking for crashes and memory leaks.\n"
1740a9542b1bSdrh "Options:\n"
17411421d980Sdrh "  --cell-size-check    Set the PRAGMA cell_size_check=ON\n"
1742a9542b1bSdrh "  --dbid N             Use only the database where dbid=N\n"
174340e0e0dbSdrh "  --export-db DIR      Write databases to files(s) in DIR. Works with --dbid\n"
174440e0e0dbSdrh "  --export-sql DIR     Write SQL to file(s) in DIR. Also works with --sqlid\n"
1745a9542b1bSdrh "  --help               Show this help text\n"
17465180d683Sdrh "  --info               Show information about SOURCE-DB w/o running tests\n"
1747672f07c6Sdrh "  --limit-depth N      Limit expression depth to N.  Default: 500\n"
1748672f07c6Sdrh "  --limit-heap N       Limit heap memory to N.  Default: 100M\n"
174953e66c3cSdrh "  --limit-mem N        Limit memory used by test SQLite instance to N bytes\n"
1750a36e01a7Sdrh "  --limit-vdbe         Panic if any test runs for more than 100,000 cycles\n"
1751ba6619d7Sdrh "  --load-sql   FILE..  Load SQL scripts fron files into SOURCE-DB\n"
1752ba6619d7Sdrh "  --load-db    FILE..  Load template databases from files into SOURCE_DB\n"
1753ba6619d7Sdrh "  --load-dbsql FILE..  Load dbsqlfuzz outputs into the xsql table\n"
1754ba6619d7Sdrh "               ^^^^------ Use \"-\" for FILE to read filenames from stdin\n"
1755d9972ef7Sdrh "  -m TEXT              Add a description to the database\n"
175615b31286Sdrh "  --native-vfs         Use the native VFS for initially empty database files\n"
1757174f8553Sdrh "  --native-malloc      Turn off MEMSYS3/5 and Lookaside\n"
175871b65e88Sdrh "  --no-recover         Do not run recovery on dbsqlfuzz databases\n"
1759ea432ba2Sdrh "  --oss-fuzz           Enable OSS-FUZZ testing\n"
1760beaf514eSdrh "  --prng-seed N        Seed value for the PRGN inside of SQLite\n"
17615180d683Sdrh "  -q|--quiet           Reduced output\n"
17629a645868Sdrh "  --rebuild            Rebuild and vacuum the database file\n"
1763e5c5f2cfSdrh "  --result-trace       Show the results of each SQL command\n"
1764075201e5Sdrh "  --script             Output CLI script instead of running tests\n"
1765672f07c6Sdrh "  --skip N             Skip the first N test cases\n"
1766aa0696eeSdrh "  --spinner            Use a spinner to show progress\n"
1767a9542b1bSdrh "  --sqlid N            Use only SQL where sqlid=N\n"
1768237f41abSdrh "  --timeout N          Maximum time for any one test in N millseconds\n"
17694c9d2281Sdrh "  -v|--verbose         Increased output.  Repeat for more output.\n"
17706e1c45efSdrh "  --vdbe-debug         Activate VDBE debugging.\n"
1771a9542b1bSdrh   );
1772a9542b1bSdrh }
1773a9542b1bSdrh 
main(int argc,char ** argv)17743b74d032Sdrh int main(int argc, char **argv){
17753b74d032Sdrh   sqlite3_int64 iBegin;        /* Start time of this program */
17763b74d032Sdrh   int quietFlag = 0;           /* True if --quiet or -q */
17773b74d032Sdrh   int verboseFlag = 0;         /* True if --verbose or -v */
17783b74d032Sdrh   char *zInsSql = 0;           /* SQL statement for --load-db or --load-sql */
17795ecf9039Sdrh   int iFirstInsArg = 0;        /* First argv[] for --load-db or --load-sql */
17803b74d032Sdrh   sqlite3 *db = 0;             /* The open database connection */
1781d9972ef7Sdrh   sqlite3_stmt *pStmt;         /* A prepared statement */
17823b74d032Sdrh   int rc;                      /* Result code from SQLite interface calls */
17833b74d032Sdrh   Blob *pSql;                  /* For looping over SQL scripts */
17843b74d032Sdrh   Blob *pDb;                   /* For looping over template databases */
17853b74d032Sdrh   int i;                       /* Loop index for the argv[] loop */
1786e5da9356Sdrh   int dbSqlOnly = 0;           /* Only use scripts that are dbsqlfuzz */
1787a9542b1bSdrh   int onlySqlid = -1;          /* --sqlid */
1788a9542b1bSdrh   int onlyDbid = -1;           /* --dbid */
178915b31286Sdrh   int nativeFlag = 0;          /* --native-vfs */
17909a645868Sdrh   int rebuildFlag = 0;         /* --rebuild */
1791d83e2831Sdrh   int vdbeLimitFlag = 0;       /* --limit-vdbe */
17925180d683Sdrh   int infoFlag = 0;            /* --info */
1793672f07c6Sdrh   int nSkip = 0;               /* --skip */
1794075201e5Sdrh   int bScript = 0;             /* --script */
1795aa0696eeSdrh   int bSpinner = 0;            /* True for --spinner */
179694701b04Sdrh   int timeoutTest = 0;         /* undocumented --timeout-test flag */
1797e5c5f2cfSdrh   int runFlags = 0;            /* Flags sent to runSql() */
1798d9972ef7Sdrh   char *zMsg = 0;              /* Add this message */
1799d9972ef7Sdrh   int nSrcDb = 0;              /* Number of source databases */
1800d9972ef7Sdrh   char **azSrcDb = 0;          /* Array of source database names */
1801d9972ef7Sdrh   int iSrcDb;                  /* Loop over all source databases */
1802d9972ef7Sdrh   int nTest = 0;               /* Total number of tests performed */
1803d9972ef7Sdrh   char *zDbName = "";          /* Appreviated name of a source database */
18045ecf9039Sdrh   const char *zFailCode = 0;   /* Value of the TEST_FAILURE env variable */
18051421d980Sdrh   int cellSzCkFlag = 0;        /* --cell-size-check */
18065ecf9039Sdrh   int sqlFuzz = 0;             /* True for SQL fuzz. False for DB fuzz */
1807237f41abSdrh   int iTimeout = 120000;       /* Default 120-second timeout */
180831999c5cSdrh   int nMem = 0;                /* Memory limit override */
1809362b66f0Sdrh   int nMemThisDb = 0;          /* Memory limit set by the CONFIG table */
181040e0e0dbSdrh   char *zExpDb = 0;            /* Write Databases to files in this directory */
181140e0e0dbSdrh   char *zExpSql = 0;           /* Write SQL to files in this directory */
18126653fbe9Sdrh   void *pHeap = 0;             /* Heap for use by SQLite */
1813ea432ba2Sdrh   int ossFuzz = 0;             /* enable OSS-FUZZ testing */
1814362b66f0Sdrh   int ossFuzzThisDb = 0;       /* ossFuzz value for this particular database */
1815174f8553Sdrh   int nativeMalloc = 0;        /* Turn off MEMSYS3/5 and lookaside if true */
1816beaf514eSdrh   sqlite3_vfs *pDfltVfs;       /* The default VFS */
1817f2cf412aSdrh   int openFlags4Data;          /* Flags for sqlite3_open_v2() */
1818237f41abSdrh   int bTimer = 0;              /* Show elapse time for each test */
1819725a9c7fSdrh   int nV;                      /* How much to increase verbosity with -vvvv */
1820237f41abSdrh   sqlite3_int64 tmStart;       /* Start of each test */
18213b74d032Sdrh 
1822be536561Sdrh   sqlite3_config(SQLITE_CONFIG_URI,1);
182339b3bcf8Sdrh   registerOomSimulator();
18248055a3eaSdrh   sqlite3_initialize();
18253b74d032Sdrh   iBegin = timeOfDay();
182694701b04Sdrh #ifdef __unix__
1827a7648f02Sdrh   signal(SIGALRM, signalHandler);
1828a7648f02Sdrh   signal(SIGSEGV, signalHandler);
1829a7648f02Sdrh   signal(SIGABRT, signalHandler);
183094701b04Sdrh #endif
18313b74d032Sdrh   g.zArgv0 = argv[0];
1832f2cf412aSdrh   openFlags4Data = SQLITE_OPEN_READONLY;
18334d6fda73Sdrh   zFailCode = getenv("TEST_FAILURE");
1834beaf514eSdrh   pDfltVfs = sqlite3_vfs_find(0);
1835beaf514eSdrh   inmemVfsRegister(1);
18363b74d032Sdrh   for(i=1; i<argc; i++){
18373b74d032Sdrh     const char *z = argv[i];
18383b74d032Sdrh     if( z[0]=='-' ){
18393b74d032Sdrh       z++;
18403b74d032Sdrh       if( z[0]=='-' ) z++;
18411421d980Sdrh       if( strcmp(z,"cell-size-check")==0 ){
18421421d980Sdrh         cellSzCkFlag = 1;
18431421d980Sdrh       }else
1844a9542b1bSdrh       if( strcmp(z,"dbid")==0 ){
1845a9542b1bSdrh         if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
184653e66c3cSdrh         onlyDbid = integerValue(argv[++i]);
1847a9542b1bSdrh       }else
184840e0e0dbSdrh       if( strcmp(z,"export-db")==0 ){
184940e0e0dbSdrh         if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
185040e0e0dbSdrh         zExpDb = argv[++i];
185140e0e0dbSdrh       }else
1852e5da9356Sdrh       if( strcmp(z,"export-sql")==0 || strcmp(z,"export-dbsql")==0 ){
185340e0e0dbSdrh         if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
185440e0e0dbSdrh         zExpSql = argv[++i];
185540e0e0dbSdrh       }else
18563b74d032Sdrh       if( strcmp(z,"help")==0 ){
18573b74d032Sdrh         showHelp();
18583b74d032Sdrh         return 0;
18593b74d032Sdrh       }else
18605180d683Sdrh       if( strcmp(z,"info")==0 ){
18615180d683Sdrh         infoFlag = 1;
18625180d683Sdrh       }else
1863be03cc9fSdrh       if( strcmp(z,"limit-depth")==0 ){
1864be03cc9fSdrh         if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
1865be03cc9fSdrh         depthLimit = integerValue(argv[++i]);
1866be03cc9fSdrh       }else
1867672f07c6Sdrh       if( strcmp(z,"limit-heap")==0 ){
1868672f07c6Sdrh         if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
1869672f07c6Sdrh         heapLimit = integerValue(argv[++i]);
1870672f07c6Sdrh       }else
187153e66c3cSdrh       if( strcmp(z,"limit-mem")==0 ){
187253e66c3cSdrh         if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
187353e66c3cSdrh         nMem = integerValue(argv[++i]);
187453e66c3cSdrh       }else
1875d83e2831Sdrh       if( strcmp(z,"limit-vdbe")==0 ){
1876d83e2831Sdrh         vdbeLimitFlag = 1;
1877d83e2831Sdrh       }else
18783b74d032Sdrh       if( strcmp(z,"load-sql")==0 ){
1879a8781d9dSdrh         zInsSql = "INSERT INTO xsql(sqltext)"
1880a8781d9dSdrh                   "VALUES(CAST(readtextfile(?1) AS text))";
18813b74d032Sdrh         iFirstInsArg = i+1;
1882f2cf412aSdrh         openFlags4Data = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
18833b74d032Sdrh         break;
18843b74d032Sdrh       }else
18853b74d032Sdrh       if( strcmp(z,"load-db")==0 ){
18863b74d032Sdrh         zInsSql = "INSERT INTO db(dbcontent) VALUES(readfile(?1))";
18873b74d032Sdrh         iFirstInsArg = i+1;
1888f2cf412aSdrh         openFlags4Data = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
18893b74d032Sdrh         break;
18903b74d032Sdrh       }else
1891e5da9356Sdrh       if( strcmp(z,"load-dbsql")==0 ){
1892a8781d9dSdrh         zInsSql = "INSERT INTO xsql(sqltext)"
1893662bebb6Sdrh                   "VALUES(readfile(?1))";
1894e5da9356Sdrh         iFirstInsArg = i+1;
1895e5da9356Sdrh         openFlags4Data = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
1896e5da9356Sdrh         dbSqlOnly = 1;
1897e5da9356Sdrh         break;
1898e5da9356Sdrh       }else
1899d9972ef7Sdrh       if( strcmp(z,"m")==0 ){
1900d9972ef7Sdrh         if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
1901d9972ef7Sdrh         zMsg = argv[++i];
1902f2cf412aSdrh         openFlags4Data = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
1903d9972ef7Sdrh       }else
1904174f8553Sdrh       if( strcmp(z,"native-malloc")==0 ){
1905174f8553Sdrh         nativeMalloc = 1;
1906174f8553Sdrh       }else
190715b31286Sdrh       if( strcmp(z,"native-vfs")==0 ){
190815b31286Sdrh         nativeFlag = 1;
190915b31286Sdrh       }else
191071b65e88Sdrh       if( strcmp(z,"no-recover")==0 ){
191171b65e88Sdrh         bNoRecover = 1;
191271b65e88Sdrh       }else
1913ea432ba2Sdrh       if( strcmp(z,"oss-fuzz")==0 ){
1914ea432ba2Sdrh         ossFuzz = 1;
1915ea432ba2Sdrh       }else
1916beaf514eSdrh       if( strcmp(z,"prng-seed")==0 ){
1917beaf514eSdrh         if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
1918beaf514eSdrh         g.uRandom = atoi(argv[++i]);
1919beaf514eSdrh       }else
19203b74d032Sdrh       if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){
19213b74d032Sdrh         quietFlag = 1;
19223b74d032Sdrh         verboseFlag = 0;
1923a47e709eSdrh         eVerbosity = 0;
19243b74d032Sdrh       }else
19259a645868Sdrh       if( strcmp(z,"rebuild")==0 ){
19269a645868Sdrh         rebuildFlag = 1;
1927f2cf412aSdrh         openFlags4Data = SQLITE_OPEN_READWRITE;
19289a645868Sdrh       }else
1929e5c5f2cfSdrh       if( strcmp(z,"result-trace")==0 ){
1930e5c5f2cfSdrh         runFlags |= SQL_OUTPUT;
1931e5c5f2cfSdrh       }else
1932075201e5Sdrh       if( strcmp(z,"script")==0 ){
1933075201e5Sdrh         bScript = 1;
1934075201e5Sdrh       }else
1935672f07c6Sdrh       if( strcmp(z,"skip")==0 ){
1936672f07c6Sdrh         if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
1937672f07c6Sdrh         nSkip = atoi(argv[++i]);
1938672f07c6Sdrh       }else
1939aa0696eeSdrh       if( strcmp(z,"spinner")==0 ){
1940aa0696eeSdrh         bSpinner = 1;
1941aa0696eeSdrh       }else
1942237f41abSdrh       if( strcmp(z,"timer")==0 ){
1943237f41abSdrh         bTimer = 1;
1944237f41abSdrh       }else
1945a9542b1bSdrh       if( strcmp(z,"sqlid")==0 ){
1946a9542b1bSdrh         if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
194753e66c3cSdrh         onlySqlid = integerValue(argv[++i]);
1948a9542b1bSdrh       }else
194992298637Sdrh       if( strcmp(z,"timeout")==0 ){
195092298637Sdrh         if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
195153e66c3cSdrh         iTimeout = integerValue(argv[++i]);
195292298637Sdrh       }else
195394701b04Sdrh       if( strcmp(z,"timeout-test")==0 ){
195494701b04Sdrh         timeoutTest = 1;
195594701b04Sdrh #ifndef __unix__
195694701b04Sdrh         fatalError("timeout is not available on non-unix systems");
195794701b04Sdrh #endif
195894701b04Sdrh       }else
19596e1c45efSdrh       if( strcmp(z,"vdbe-debug")==0 ){
19606e1c45efSdrh         bVdbeDebug = 1;
19616e1c45efSdrh       }else
1962725a9c7fSdrh       if( strcmp(z,"verbose")==0 ){
19633b74d032Sdrh         quietFlag = 0;
19644c9d2281Sdrh         verboseFlag++;
1965a47e709eSdrh         eVerbosity++;
19664c9d2281Sdrh         if( verboseFlag>1 ) runFlags |= SQL_TRACE;
19673b74d032Sdrh       }else
1968725a9c7fSdrh       if( (nV = numberOfVChar(z))>=1 ){
1969725a9c7fSdrh         quietFlag = 0;
1970725a9c7fSdrh         verboseFlag += nV;
1971725a9c7fSdrh         eVerbosity += nV;
1972725a9c7fSdrh         if( verboseFlag>1 ) runFlags |= SQL_TRACE;
1973725a9c7fSdrh       }else
1974a47e709eSdrh       if( strcmp(z,"version")==0 ){
1975a47e709eSdrh         int ii;
1976ed457037Sdrh         const char *zz;
1977a47e709eSdrh         printf("SQLite %s %s\n", sqlite3_libversion(), sqlite3_sourceid());
1978ed457037Sdrh         for(ii=0; (zz = sqlite3_compileoption_get(ii))!=0; ii++){
1979ed457037Sdrh           printf("%s\n", zz);
1980a47e709eSdrh         }
1981a47e709eSdrh         return 0;
1982a47e709eSdrh       }else
1983662bebb6Sdrh       if( strcmp(z,"is-dbsql")==0 ){
1984662bebb6Sdrh         i++;
1985662bebb6Sdrh         for(i++; i<argc; i++){
1986662bebb6Sdrh           long nData;
1987662bebb6Sdrh           char *aData = readFile(argv[i], &nData);
1988be2d6fddSdrh           printf("%d %s\n", isDbSql((unsigned char*)aData,nData), argv[i]);
1989662bebb6Sdrh           sqlite3_free(aData);
1990662bebb6Sdrh         }
1991662bebb6Sdrh         exit(0);
1992662bebb6Sdrh       }else
19933b74d032Sdrh       {
19943b74d032Sdrh         fatalError("unknown option: %s", argv[i]);
19953b74d032Sdrh       }
19963b74d032Sdrh     }else{
1997d9972ef7Sdrh       nSrcDb++;
1998d9972ef7Sdrh       azSrcDb = safe_realloc(azSrcDb, nSrcDb*sizeof(azSrcDb[0]));
1999d9972ef7Sdrh       azSrcDb[nSrcDb-1] = argv[i];
20003b74d032Sdrh     }
20013b74d032Sdrh   }
2002d9972ef7Sdrh   if( nSrcDb==0 ) fatalError("no source database specified");
2003d9972ef7Sdrh   if( nSrcDb>1 ){
2004d9972ef7Sdrh     if( zMsg ){
2005d9972ef7Sdrh       fatalError("cannot change the description of more than one database");
2006d9972ef7Sdrh     }
2007d9972ef7Sdrh     if( zInsSql ){
2008d9972ef7Sdrh       fatalError("cannot import into more than one database");
2009d9972ef7Sdrh     }
2010d9972ef7Sdrh   }
2011d9972ef7Sdrh 
2012d9972ef7Sdrh   /* Process each source database separately */
2013d9972ef7Sdrh   for(iSrcDb=0; iSrcDb<nSrcDb; iSrcDb++){
201448b4bf26Sdrh     char *zRawData = 0;
201548b4bf26Sdrh     long nRawData = 0;
2016a7648f02Sdrh     g.zDbFile = azSrcDb[iSrcDb];
2017beaf514eSdrh     rc = sqlite3_open_v2(azSrcDb[iSrcDb], &db,
2018f2cf412aSdrh                          openFlags4Data, pDfltVfs->zName);
201948b4bf26Sdrh     if( rc==SQLITE_OK ){
202048b4bf26Sdrh       rc = sqlite3_exec(db, "SELECT count(*) FROM sqlite_schema", 0, 0, 0);
202148b4bf26Sdrh     }
20223b74d032Sdrh     if( rc ){
202348b4bf26Sdrh       sqlite3_close(db);
202448b4bf26Sdrh       zRawData = readFile(azSrcDb[iSrcDb], &nRawData);
202548b4bf26Sdrh       if( zRawData==0 ){
202648b4bf26Sdrh         fatalError("input file \"%s\" is not recognized\n", azSrcDb[iSrcDb]);
202748b4bf26Sdrh       }
202848b4bf26Sdrh       sqlite3_open(":memory:", &db);
20293b74d032Sdrh     }
20305180d683Sdrh 
20315180d683Sdrh     /* Print the description, if there is one */
20325180d683Sdrh     if( infoFlag ){
20335180d683Sdrh       int n;
20345180d683Sdrh       zDbName = azSrcDb[iSrcDb];
20355180d683Sdrh       i = (int)strlen(zDbName) - 1;
20365180d683Sdrh       while( i>0 && zDbName[i-1]!='/' && zDbName[i-1]!='\\' ){ i--; }
20375180d683Sdrh       zDbName += i;
20385180d683Sdrh       sqlite3_prepare_v2(db, "SELECT msg FROM readme", -1, &pStmt, 0);
20395180d683Sdrh       if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
20405180d683Sdrh         printf("%s: %s", zDbName, sqlite3_column_text(pStmt,0));
20415180d683Sdrh       }else{
20425180d683Sdrh         printf("%s: (empty \"readme\")", zDbName);
20435180d683Sdrh       }
20445180d683Sdrh       sqlite3_finalize(pStmt);
20455180d683Sdrh       sqlite3_prepare_v2(db, "SELECT count(*) FROM db", -1, &pStmt, 0);
20465180d683Sdrh       if( pStmt
20475180d683Sdrh        && sqlite3_step(pStmt)==SQLITE_ROW
20485180d683Sdrh        && (n = sqlite3_column_int(pStmt,0))>0
20495180d683Sdrh       ){
20505180d683Sdrh         printf(" - %d DBs", n);
20515180d683Sdrh       }
20525180d683Sdrh       sqlite3_finalize(pStmt);
20535180d683Sdrh       sqlite3_prepare_v2(db, "SELECT count(*) FROM xsql", -1, &pStmt, 0);
20545180d683Sdrh       if( pStmt
20555180d683Sdrh        && sqlite3_step(pStmt)==SQLITE_ROW
20565180d683Sdrh        && (n = sqlite3_column_int(pStmt,0))>0
20575180d683Sdrh       ){
20585180d683Sdrh         printf(" - %d scripts", n);
20595180d683Sdrh       }
20605180d683Sdrh       sqlite3_finalize(pStmt);
20615180d683Sdrh       printf("\n");
20625180d683Sdrh       sqlite3_close(db);
206348b4bf26Sdrh       sqlite3_free(zRawData);
20645180d683Sdrh       continue;
20655180d683Sdrh     }
20665180d683Sdrh 
20673b74d032Sdrh     rc = sqlite3_exec(db,
20683b74d032Sdrh        "CREATE TABLE IF NOT EXISTS db(\n"
20693b74d032Sdrh        "  dbid INTEGER PRIMARY KEY, -- database id\n"
20703b74d032Sdrh        "  dbcontent BLOB            -- database disk file image\n"
20713b74d032Sdrh        ");\n"
20723b74d032Sdrh        "CREATE TABLE IF NOT EXISTS xsql(\n"
20733b74d032Sdrh        "  sqlid INTEGER PRIMARY KEY,   -- SQL script id\n"
20743b74d032Sdrh        "  sqltext TEXT                 -- Text of SQL statements to run\n"
2075d9972ef7Sdrh        ");"
2076d9972ef7Sdrh        "CREATE TABLE IF NOT EXISTS readme(\n"
2077d9972ef7Sdrh        "  msg TEXT -- Human-readable description of this file\n"
20783b74d032Sdrh        ");", 0, 0, 0);
20793b74d032Sdrh     if( rc ) fatalError("cannot create schema: %s", sqlite3_errmsg(db));
2080d9972ef7Sdrh     if( zMsg ){
2081d9972ef7Sdrh       char *zSql;
2082d9972ef7Sdrh       zSql = sqlite3_mprintf(
2083d9972ef7Sdrh                "DELETE FROM readme; INSERT INTO readme(msg) VALUES(%Q)", zMsg);
2084d9972ef7Sdrh       rc = sqlite3_exec(db, zSql, 0, 0, 0);
2085d9972ef7Sdrh       sqlite3_free(zSql);
2086d9972ef7Sdrh       if( rc ) fatalError("cannot change description: %s", sqlite3_errmsg(db));
2087d9972ef7Sdrh     }
208848b4bf26Sdrh     if( zRawData ){
208948b4bf26Sdrh       zInsSql = "INSERT INTO xsql(sqltext) VALUES(?1)";
209048b4bf26Sdrh       rc = sqlite3_prepare_v2(db, zInsSql, -1, &pStmt, 0);
209148b4bf26Sdrh       if( rc ) fatalError("cannot prepare statement [%s]: %s",
209248b4bf26Sdrh                           zInsSql, sqlite3_errmsg(db));
209348b4bf26Sdrh       sqlite3_bind_text(pStmt, 1, zRawData, nRawData, SQLITE_STATIC);
209448b4bf26Sdrh       sqlite3_step(pStmt);
209548b4bf26Sdrh       rc = sqlite3_reset(pStmt);
209648b4bf26Sdrh       if( rc ) fatalError("insert failed for %s", argv[i]);
209748b4bf26Sdrh       sqlite3_finalize(pStmt);
209848b4bf26Sdrh       rebuild_database(db, dbSqlOnly);
209948b4bf26Sdrh       zInsSql = 0;
210048b4bf26Sdrh       sqlite3_free(zRawData);
210148b4bf26Sdrh       zRawData = 0;
210248b4bf26Sdrh     }
2103362b66f0Sdrh     ossFuzzThisDb = ossFuzz;
2104362b66f0Sdrh 
2105362b66f0Sdrh     /* If the CONFIG(name,value) table exists, read db-specific settings
2106362b66f0Sdrh     ** from that table */
2107362b66f0Sdrh     if( sqlite3_table_column_metadata(db,0,"config",0,0,0,0,0,0)==SQLITE_OK ){
21085ecf9039Sdrh       rc = sqlite3_prepare_v2(db, "SELECT name, value FROM config",
21095ecf9039Sdrh                                   -1, &pStmt, 0);
2110362b66f0Sdrh       if( rc ) fatalError("cannot prepare query of CONFIG table: %s",
2111362b66f0Sdrh                           sqlite3_errmsg(db));
2112362b66f0Sdrh       while( SQLITE_ROW==sqlite3_step(pStmt) ){
2113362b66f0Sdrh         const char *zName = (const char *)sqlite3_column_text(pStmt,0);
2114362b66f0Sdrh         if( zName==0 ) continue;
2115362b66f0Sdrh         if( strcmp(zName, "oss-fuzz")==0 ){
2116362b66f0Sdrh           ossFuzzThisDb = sqlite3_column_int(pStmt,1);
2117362b66f0Sdrh           if( verboseFlag ) printf("Config: oss-fuzz=%d\n", ossFuzzThisDb);
2118362b66f0Sdrh         }
211931999c5cSdrh         if( strcmp(zName, "limit-mem")==0 ){
2120362b66f0Sdrh           nMemThisDb = sqlite3_column_int(pStmt,1);
2121362b66f0Sdrh           if( verboseFlag ) printf("Config: limit-mem=%d\n", nMemThisDb);
2122362b66f0Sdrh         }
2123362b66f0Sdrh       }
2124362b66f0Sdrh       sqlite3_finalize(pStmt);
2125362b66f0Sdrh     }
2126362b66f0Sdrh 
21273b74d032Sdrh     if( zInsSql ){
21283b74d032Sdrh       sqlite3_create_function(db, "readfile", 1, SQLITE_UTF8, 0,
21293b74d032Sdrh                               readfileFunc, 0, 0);
2130a8781d9dSdrh       sqlite3_create_function(db, "readtextfile", 1, SQLITE_UTF8, 0,
2131a8781d9dSdrh                               readtextfileFunc, 0, 0);
2132e5da9356Sdrh       sqlite3_create_function(db, "isdbsql", 1, SQLITE_UTF8, 0,
2133e5da9356Sdrh                               isDbSqlFunc, 0, 0);
21343b74d032Sdrh       rc = sqlite3_prepare_v2(db, zInsSql, -1, &pStmt, 0);
21353b74d032Sdrh       if( rc ) fatalError("cannot prepare statement [%s]: %s",
21363b74d032Sdrh                           zInsSql, sqlite3_errmsg(db));
21373b74d032Sdrh       rc = sqlite3_exec(db, "BEGIN", 0, 0, 0);
21383b74d032Sdrh       if( rc ) fatalError("cannot start a transaction");
21393b74d032Sdrh       for(i=iFirstInsArg; i<argc; i++){
2140ba6619d7Sdrh         if( strcmp(argv[i],"-")==0 ){
2141ba6619d7Sdrh           /* A filename of "-" means read multiple filenames from stdin */
214215212700Sdrh           char zLine[2000];
2143ba6619d7Sdrh           while( rc==0 && fgets(zLine,sizeof(zLine),stdin)!=0 ){
2144ba6619d7Sdrh             size_t kk = strlen(zLine);
214559607247Sdrh             while( kk>0 && zLine[kk-1]<=' ' ) kk--;
21469d41caf3Sdrh             sqlite3_bind_text(pStmt, 1, zLine, (int)kk, SQLITE_STATIC);
214759607247Sdrh             if( verboseFlag ) printf("loading %.*s\n", (int)kk, zLine);
2148ba6619d7Sdrh             sqlite3_step(pStmt);
2149ba6619d7Sdrh             rc = sqlite3_reset(pStmt);
2150ba6619d7Sdrh             if( rc ) fatalError("insert failed for %s", zLine);
2151ba6619d7Sdrh           }
2152ba6619d7Sdrh         }else{
21533b74d032Sdrh           sqlite3_bind_text(pStmt, 1, argv[i], -1, SQLITE_STATIC);
215459607247Sdrh           if( verboseFlag ) printf("loading %s\n", argv[i]);
21553b74d032Sdrh           sqlite3_step(pStmt);
21563b74d032Sdrh           rc = sqlite3_reset(pStmt);
21573b74d032Sdrh           if( rc ) fatalError("insert failed for %s", argv[i]);
21583b74d032Sdrh         }
2159ba6619d7Sdrh       }
21603b74d032Sdrh       sqlite3_finalize(pStmt);
21613b74d032Sdrh       rc = sqlite3_exec(db, "COMMIT", 0, 0, 0);
21625ecf9039Sdrh       if( rc ) fatalError("cannot commit the transaction: %s",
21635ecf9039Sdrh                           sqlite3_errmsg(db));
2164e5da9356Sdrh       rebuild_database(db, dbSqlOnly);
21653b74d032Sdrh       sqlite3_close(db);
21663b74d032Sdrh       return 0;
21673b74d032Sdrh     }
216816f0582cSdrh     rc = sqlite3_exec(db, "PRAGMA query_only=1;", 0, 0, 0);
216916f0582cSdrh     if( rc ) fatalError("cannot set database to query-only");
217040e0e0dbSdrh     if( zExpDb!=0 || zExpSql!=0 ){
217140e0e0dbSdrh       sqlite3_create_function(db, "writefile", 2, SQLITE_UTF8, 0,
217240e0e0dbSdrh                               writefileFunc, 0, 0);
217340e0e0dbSdrh       if( zExpDb!=0 ){
217440e0e0dbSdrh         const char *zExDb =
217540e0e0dbSdrh           "SELECT writefile(printf('%s/db%06d.db',?1,dbid),dbcontent),"
217640e0e0dbSdrh           "       dbid, printf('%s/db%06d.db',?1,dbid), length(dbcontent)"
217740e0e0dbSdrh           "  FROM db WHERE ?2<0 OR dbid=?2;";
217840e0e0dbSdrh         rc = sqlite3_prepare_v2(db, zExDb, -1, &pStmt, 0);
217940e0e0dbSdrh         if( rc ) fatalError("cannot prepare statement [%s]: %s",
218040e0e0dbSdrh                             zExDb, sqlite3_errmsg(db));
218140e0e0dbSdrh         sqlite3_bind_text64(pStmt, 1, zExpDb, strlen(zExpDb),
218240e0e0dbSdrh                             SQLITE_STATIC, SQLITE_UTF8);
218340e0e0dbSdrh         sqlite3_bind_int(pStmt, 2, onlyDbid);
218440e0e0dbSdrh         while( sqlite3_step(pStmt)==SQLITE_ROW ){
218540e0e0dbSdrh           printf("write db-%d (%d bytes) into %s\n",
218640e0e0dbSdrh              sqlite3_column_int(pStmt,1),
218740e0e0dbSdrh              sqlite3_column_int(pStmt,3),
218840e0e0dbSdrh              sqlite3_column_text(pStmt,2));
218940e0e0dbSdrh         }
219040e0e0dbSdrh         sqlite3_finalize(pStmt);
219140e0e0dbSdrh       }
219240e0e0dbSdrh       if( zExpSql!=0 ){
219340e0e0dbSdrh         const char *zExSql =
219440e0e0dbSdrh           "SELECT writefile(printf('%s/sql%06d.txt',?1,sqlid),sqltext),"
219540e0e0dbSdrh           "       sqlid, printf('%s/sql%06d.txt',?1,sqlid), length(sqltext)"
219640e0e0dbSdrh           "  FROM xsql WHERE ?2<0 OR sqlid=?2;";
219740e0e0dbSdrh         rc = sqlite3_prepare_v2(db, zExSql, -1, &pStmt, 0);
219840e0e0dbSdrh         if( rc ) fatalError("cannot prepare statement [%s]: %s",
219940e0e0dbSdrh                             zExSql, sqlite3_errmsg(db));
220040e0e0dbSdrh         sqlite3_bind_text64(pStmt, 1, zExpSql, strlen(zExpSql),
220140e0e0dbSdrh                             SQLITE_STATIC, SQLITE_UTF8);
220240e0e0dbSdrh         sqlite3_bind_int(pStmt, 2, onlySqlid);
220340e0e0dbSdrh         while( sqlite3_step(pStmt)==SQLITE_ROW ){
220440e0e0dbSdrh           printf("write sql-%d (%d bytes) into %s\n",
220540e0e0dbSdrh              sqlite3_column_int(pStmt,1),
220640e0e0dbSdrh              sqlite3_column_int(pStmt,3),
220740e0e0dbSdrh              sqlite3_column_text(pStmt,2));
220840e0e0dbSdrh         }
220940e0e0dbSdrh         sqlite3_finalize(pStmt);
221040e0e0dbSdrh       }
221140e0e0dbSdrh       sqlite3_close(db);
221240e0e0dbSdrh       return 0;
221340e0e0dbSdrh     }
22143b74d032Sdrh 
22153b74d032Sdrh     /* Load all SQL script content and all initial database images from the
22163b74d032Sdrh     ** source db
22173b74d032Sdrh     */
2218a9542b1bSdrh     blobListLoadFromDb(db, "SELECT sqlid, sqltext FROM xsql", onlySqlid,
2219a9542b1bSdrh                            &g.nSql, &g.pFirstSql);
22203b74d032Sdrh     if( g.nSql==0 ) fatalError("need at least one SQL script");
2221a9542b1bSdrh     blobListLoadFromDb(db, "SELECT dbid, dbcontent FROM db", onlyDbid,
2222a9542b1bSdrh                        &g.nDb, &g.pFirstDb);
22233b74d032Sdrh     if( g.nDb==0 ){
22243b74d032Sdrh       g.pFirstDb = safe_realloc(0, sizeof(Blob));
22253b74d032Sdrh       memset(g.pFirstDb, 0, sizeof(Blob));
22263b74d032Sdrh       g.pFirstDb->id = 1;
2227e5c5f2cfSdrh       g.pFirstDb->seq = 0;
22283b74d032Sdrh       g.nDb = 1;
2229d83e2831Sdrh       sqlFuzz = 1;
22303b74d032Sdrh     }
22313b74d032Sdrh 
2232d9972ef7Sdrh     /* Print the description, if there is one */
2233075201e5Sdrh     if( !quietFlag && !bScript ){
2234d9972ef7Sdrh       zDbName = azSrcDb[iSrcDb];
2235e683b898Sdrh       i = (int)strlen(zDbName) - 1;
2236d9972ef7Sdrh       while( i>0 && zDbName[i-1]!='/' && zDbName[i-1]!='\\' ){ i--; }
2237d9972ef7Sdrh       zDbName += i;
2238d9972ef7Sdrh       sqlite3_prepare_v2(db, "SELECT msg FROM readme", -1, &pStmt, 0);
2239d9972ef7Sdrh       if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
2240d9972ef7Sdrh         printf("%s: %s\n", zDbName, sqlite3_column_text(pStmt,0));
2241d9972ef7Sdrh       }
2242d9972ef7Sdrh       sqlite3_finalize(pStmt);
2243d9972ef7Sdrh     }
22443b74d032Sdrh 
22459a645868Sdrh     /* Rebuild the database, if requested */
22469a645868Sdrh     if( rebuildFlag ){
22479a645868Sdrh       if( !quietFlag ){
22489a645868Sdrh         printf("%s: rebuilding... ", zDbName);
22499a645868Sdrh         fflush(stdout);
22509a645868Sdrh       }
2251e5da9356Sdrh       rebuild_database(db, 0);
22529a645868Sdrh       if( !quietFlag ) printf("done\n");
22539a645868Sdrh     }
22549a645868Sdrh 
22553b74d032Sdrh     /* Close the source database.  Verify that no SQLite memory allocations are
22563b74d032Sdrh     ** outstanding.
22573b74d032Sdrh     */
22583b74d032Sdrh     sqlite3_close(db);
22593b74d032Sdrh     if( sqlite3_memory_used()>0 ){
22603b74d032Sdrh       fatalError("SQLite has memory in use before the start of testing");
22613b74d032Sdrh     }
22623b74d032Sdrh 
226353e66c3cSdrh     /* Limit available memory, if requested */
226453e66c3cSdrh     sqlite3_shutdown();
226539b3bcf8Sdrh 
226631999c5cSdrh     if( nMemThisDb>0 && nMem==0 ){
226731999c5cSdrh       if( !nativeMalloc ){
2268362b66f0Sdrh         pHeap = realloc(pHeap, nMemThisDb);
226953e66c3cSdrh         if( pHeap==0 ){
227053e66c3cSdrh           fatalError("failed to allocate %d bytes of heap memory", nMem);
227153e66c3cSdrh         }
2272362b66f0Sdrh         sqlite3_config(SQLITE_CONFIG_HEAP, pHeap, nMemThisDb, 128);
227331999c5cSdrh       }else{
227431999c5cSdrh         sqlite3_hard_heap_limit64((sqlite3_int64)nMemThisDb);
227531999c5cSdrh       }
227631999c5cSdrh     }else{
227731999c5cSdrh       sqlite3_hard_heap_limit64(0);
227853e66c3cSdrh     }
227953e66c3cSdrh 
2280174f8553Sdrh     /* Disable lookaside with the --native-malloc option */
2281174f8553Sdrh     if( nativeMalloc ){
2282174f8553Sdrh       sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 0, 0);
2283174f8553Sdrh     }
2284174f8553Sdrh 
2285beaf514eSdrh     /* Reset the in-memory virtual filesystem */
22863b74d032Sdrh     formatVfs();
22873b74d032Sdrh 
22883b74d032Sdrh     /* Run a test using each SQL script against each database.
22893b74d032Sdrh     */
2290075201e5Sdrh     if( !verboseFlag && !quietFlag && !bSpinner && !bScript ){
2291075201e5Sdrh       printf("%s:", zDbName);
2292075201e5Sdrh     }
22933b74d032Sdrh     for(pSql=g.pFirstSql; pSql; pSql=pSql->pNext){
2294237f41abSdrh       tmStart = timeOfDay();
2295a47e709eSdrh       if( isDbSql(pSql->a, pSql->sz) ){
2296a47e709eSdrh         sqlite3_snprintf(sizeof(g.zTestName), g.zTestName, "sqlid=%d",pSql->id);
2297075201e5Sdrh         if( bScript ){
2298075201e5Sdrh           /* No progress output */
2299075201e5Sdrh         }else if( bSpinner ){
2300aa0696eeSdrh           int nTotal =g.nSql;
2301aa0696eeSdrh           int idx = pSql->seq;
2302aa0696eeSdrh           printf("\r%s: %d/%d   ", zDbName, idx, nTotal);
2303aa0696eeSdrh           fflush(stdout);
2304aa0696eeSdrh         }else if( verboseFlag ){
2305a47e709eSdrh           printf("%s\n", g.zTestName);
2306a47e709eSdrh           fflush(stdout);
2307a47e709eSdrh         }else if( !quietFlag ){
2308a47e709eSdrh           static int prevAmt = -1;
2309a47e709eSdrh           int idx = pSql->seq;
2310a47e709eSdrh           int amt = idx*10/(g.nSql);
2311a47e709eSdrh           if( amt!=prevAmt ){
2312a47e709eSdrh             printf(" %d%%", amt*10);
2313a47e709eSdrh             fflush(stdout);
2314a47e709eSdrh             prevAmt = amt;
2315a47e709eSdrh           }
2316a47e709eSdrh         }
2317672f07c6Sdrh         if( nSkip>0 ){
2318672f07c6Sdrh           nSkip--;
2319672f07c6Sdrh         }else{
2320075201e5Sdrh           runCombinedDbSqlInput(pSql->a, pSql->sz, iTimeout, bScript, pSql->id);
2321672f07c6Sdrh         }
2322a47e709eSdrh         nTest++;
2323075201e5Sdrh         if( bTimer && !bScript ){
2324237f41abSdrh           sqlite3_int64 tmEnd = timeOfDay();
2325237f41abSdrh           printf("%lld %s\n", tmEnd - tmStart, g.zTestName);
2326237f41abSdrh         }
2327a47e709eSdrh         g.zTestName[0] = 0;
232839b3bcf8Sdrh         disableOom();
2329a47e709eSdrh         continue;
2330a47e709eSdrh       }
23313b74d032Sdrh       for(pDb=g.pFirstDb; pDb; pDb=pDb->pNext){
233215b31286Sdrh         int openFlags;
233315b31286Sdrh         const char *zVfs = "inmem";
23343b74d032Sdrh         sqlite3_snprintf(sizeof(g.zTestName), g.zTestName, "sqlid=%d,dbid=%d",
23353b74d032Sdrh                          pSql->id, pDb->id);
2336075201e5Sdrh         if( bScript ){
2337075201e5Sdrh           /* No progress output */
2338075201e5Sdrh         }else if( bSpinner ){
2339aa0696eeSdrh           int nTotal = g.nDb*g.nSql;
2340aa0696eeSdrh           int idx = pSql->seq*g.nDb + pDb->id - 1;
2341aa0696eeSdrh           printf("\r%s: %d/%d   ", zDbName, idx, nTotal);
2342aa0696eeSdrh           fflush(stdout);
2343aa0696eeSdrh         }else if( verboseFlag ){
23443b74d032Sdrh           printf("%s\n", g.zTestName);
23453b74d032Sdrh           fflush(stdout);
23463b74d032Sdrh         }else if( !quietFlag ){
23473b74d032Sdrh           static int prevAmt = -1;
2348e5c5f2cfSdrh           int idx = pSql->seq*g.nDb + pDb->id - 1;
23493b74d032Sdrh           int amt = idx*10/(g.nDb*g.nSql);
23503b74d032Sdrh           if( amt!=prevAmt ){
23513b74d032Sdrh             printf(" %d%%", amt*10);
235215b31286Sdrh             fflush(stdout);
23533b74d032Sdrh             prevAmt = amt;
23543b74d032Sdrh           }
23553b74d032Sdrh         }
2356672f07c6Sdrh         if( nSkip>0 ){
2357672f07c6Sdrh           nSkip--;
2358672f07c6Sdrh           continue;
2359672f07c6Sdrh         }
2360075201e5Sdrh         if( bScript ){
2361075201e5Sdrh           char zName[100];
2362075201e5Sdrh           sqlite3_snprintf(sizeof(zName), zName, "db%06d.db",
2363075201e5Sdrh                            pDb->id>1 ? pDb->id : pSql->id);
2364075201e5Sdrh           renderDbSqlForCLI(stdout, zName,
2365075201e5Sdrh              pDb->a, pDb->sz, pSql->a, pSql->sz);
2366075201e5Sdrh           continue;
2367075201e5Sdrh         }
23683b74d032Sdrh         createVFile("main.db", pDb->sz, pDb->a);
2369beaf514eSdrh         sqlite3_randomness(0,0);
2370362b66f0Sdrh         if( ossFuzzThisDb ){
2371ea432ba2Sdrh #ifndef SQLITE_OSS_FUZZ
23725ecf9039Sdrh           fatalError("--oss-fuzz not supported: recompile"
23735ecf9039Sdrh                      " with -DSQLITE_OSS_FUZZ");
2374ea432ba2Sdrh #else
2375ea432ba2Sdrh           extern int LLVMFuzzerTestOneInput(const uint8_t*, size_t);
2376ea432ba2Sdrh           LLVMFuzzerTestOneInput((const uint8_t*)pSql->a, (size_t)pSql->sz);
2377ea432ba2Sdrh #endif
2378ea432ba2Sdrh         }else{
237915b31286Sdrh           openFlags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE;
238015b31286Sdrh           if( nativeFlag && pDb->sz==0 ){
238115b31286Sdrh             openFlags |= SQLITE_OPEN_MEMORY;
238215b31286Sdrh             zVfs = 0;
238315b31286Sdrh           }
238415b31286Sdrh           rc = sqlite3_open_v2("main.db", &db, openFlags, zVfs);
23853b74d032Sdrh           if( rc ) fatalError("cannot open inmem database");
2386dfcfff64Sdrh           sqlite3_limit(db, SQLITE_LIMIT_LENGTH, 100000000);
2387dfcfff64Sdrh           sqlite3_limit(db, SQLITE_LIMIT_LIKE_PATTERN_LENGTH, 50);
23881421d980Sdrh           if( cellSzCkFlag ) runSql(db, "PRAGMA cell_size_check=ON", runFlags);
2389237f41abSdrh           setAlarm((iTimeout+999)/1000);
23907ae05499Sdrh           /* Enable test functions */
23917ae05499Sdrh           sqlite3_test_control(SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, db);
239278057351Sdrh #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
2393d83e2831Sdrh           if( sqlFuzz || vdbeLimitFlag ){
23945ecf9039Sdrh             sqlite3_progress_handler(db, 100000, progressHandler,
23955ecf9039Sdrh                                      &vdbeLimitFlag);
2396d83e2831Sdrh           }
239778057351Sdrh #endif
2398e6e96b1bSdrh #ifdef SQLITE_TESTCTRL_PRNG_SEED
23992e6d83bcSdrh           sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SEED, 1, db);
2400e6e96b1bSdrh #endif
24016e1c45efSdrh           if( bVdbeDebug ){
24026e1c45efSdrh             sqlite3_exec(db, "PRAGMA vdbe_debug=ON", 0, 0, 0);
24036e1c45efSdrh           }
240494701b04Sdrh           do{
2405e5c5f2cfSdrh             runSql(db, (char*)pSql->a, runFlags);
240694701b04Sdrh           }while( timeoutTest );
240794701b04Sdrh           setAlarm(0);
2408174f8553Sdrh           sqlite3_exec(db, "PRAGMA temp_store_directory=''", 0, 0, 0);
24093b74d032Sdrh           sqlite3_close(db);
2410ea432ba2Sdrh         }
2411174f8553Sdrh         if( sqlite3_memory_used()>0 ){
2412174f8553Sdrh            fatalError("memory leak: %lld bytes outstanding",
2413174f8553Sdrh                       sqlite3_memory_used());
2414174f8553Sdrh         }
24153b74d032Sdrh         reformatVfs();
2416d9972ef7Sdrh         nTest++;
2417237f41abSdrh         if( bTimer ){
2418237f41abSdrh           sqlite3_int64 tmEnd = timeOfDay();
2419237f41abSdrh           printf("%lld %s\n", tmEnd - tmStart, g.zTestName);
2420237f41abSdrh         }
24213b74d032Sdrh         g.zTestName[0] = 0;
24224d6fda73Sdrh 
24234d6fda73Sdrh         /* Simulate an error if the TEST_FAILURE environment variable is "5".
24244d6fda73Sdrh         ** This is used to verify that automated test script really do spot
24254d6fda73Sdrh         ** errors that occur in this test program.
24264d6fda73Sdrh         */
24274d6fda73Sdrh         if( zFailCode ){
24284d6fda73Sdrh           if( zFailCode[0]=='5' && zFailCode[1]==0 ){
24294d6fda73Sdrh             fatalError("simulated failure");
24304d6fda73Sdrh           }else if( zFailCode[0]!=0 ){
24314d6fda73Sdrh             /* If TEST_FAILURE is something other than 5, just exit the test
24324d6fda73Sdrh             ** early */
24334d6fda73Sdrh             printf("\nExit early due to TEST_FAILURE being set\n");
24344d6fda73Sdrh             iSrcDb = nSrcDb-1;
24354d6fda73Sdrh             goto sourcedb_cleanup;
24364d6fda73Sdrh           }
24374d6fda73Sdrh         }
24383b74d032Sdrh       }
24393b74d032Sdrh     }
2440075201e5Sdrh     if( bScript ){
2441075201e5Sdrh       /* No progress output */
2442075201e5Sdrh     }else if( bSpinner ){
2443292ed6deSdrh       int nTotal = g.nDb*g.nSql;
2444292ed6deSdrh       printf("\r%s: %d/%d   \n", zDbName, nTotal, nTotal);
2445aa0696eeSdrh     }else if( !quietFlag && !verboseFlag ){
2446d9972ef7Sdrh       printf(" 100%% - %d tests\n", g.nDb*g.nSql);
24473b74d032Sdrh     }
24483b74d032Sdrh 
2449d9972ef7Sdrh     /* Clean up at the end of processing a single source database
24503b74d032Sdrh     */
24514d6fda73Sdrh   sourcedb_cleanup:
24523b74d032Sdrh     blobListFree(g.pFirstSql);
24533b74d032Sdrh     blobListFree(g.pFirstDb);
24543b74d032Sdrh     reformatVfs();
2455d9972ef7Sdrh 
2456d9972ef7Sdrh   } /* End loop over all source databases */
2457d9972ef7Sdrh 
2458075201e5Sdrh   if( !quietFlag && !bScript ){
2459d9972ef7Sdrh     sqlite3_int64 iElapse = timeOfDay() - iBegin;
2460e3bf2c8eSdrh     if( g.nInvariant ){
2461e3bf2c8eSdrh       printf("fuzzcheck: %u query invariants checked\n", g.nInvariant);
2462e3bf2c8eSdrh     }
2463d9972ef7Sdrh     printf("fuzzcheck: 0 errors out of %d tests in %d.%03d seconds\n"
2464d9972ef7Sdrh            "SQLite %s %s\n",
2465d9972ef7Sdrh            nTest, (int)(iElapse/1000), (int)(iElapse%1000),
2466d9972ef7Sdrh            sqlite3_libversion(), sqlite3_sourceid());
2467d9972ef7Sdrh   }
2468f74d35beSdrh   free(azSrcDb);
24696653fbe9Sdrh   free(pHeap);
24703b74d032Sdrh   return 0;
24713b74d032Sdrh }
2472