4 ** The author disclaims copyright to this source code. In place of
5 ** a legal notice, here is a blessing:
7 ** May you do good and not evil.
8 ** May you find forgiveness for yourself and forgive others.
9 ** May you share freely, never taking more than you give.
11 *************************************************************************
13 ** This is a utility program designed to aid running regressions tests on
14 ** the SQLite library using data from an external fuzzer, such as American
15 ** Fuzzy Lop (AFL) (http://lcamtuf.coredump.cx/afl/).
17 ** This program reads content from an SQLite database file with the following
21 ** dbid INTEGER PRIMARY KEY, -- database id
22 ** dbcontent BLOB -- database disk file image
25 ** sqlid INTEGER PRIMARY KEY, -- SQL script id
26 ** sqltext TEXT -- Text of SQL statements to run
28 ** CREATE TABLE IF NOT EXISTS readme(
29 ** msg TEXT -- Human-readable description of this test collection
32 ** For each database file in the DB table, the SQL text in the XSQL table
33 ** is run against that database. All README.MSG values are printed prior
34 ** to the start of the test (unless the --quiet option is used). If the
35 ** DB table is empty, then all entries in XSQL are run against an empty
36 ** in-memory database.
38 ** This program is looking for crashes, assertion faults, and/or memory leaks.
39 ** No attempt is made to verify the output. The assumption is that either all
40 ** of the database files or all of the SQL statements are malformed inputs,
41 ** generated by a fuzzer, that need to be checked to make sure they do not
42 ** present a security risk.
44 ** This program also includes some command-line options to help with
45 ** creation and maintenance of the source content database. The command
47 ** ./fuzzcheck database.db --load-sql FILE...
49 ** Loads all FILE... arguments into the XSQL table. The --load-db option
50 ** works the same but loads the files into the DB table. The -m option can
51 ** be used to initialize the README table. The "database.db" file is created
52 ** if it does not previously exist. Example:
54 ** ./fuzzcheck new.db --load-sql *.sql
55 ** ./fuzzcheck new.db --load-db *.db
56 ** ./fuzzcheck new.db -m 'New test cases'
58 ** The three commands above will create the "new.db" file and initialize all
59 ** tables. Then do "./fuzzcheck new.db" to run the tests.
63 ** If fuzzcheck does crash, it can be run in the debugger and the content
64 ** of the global variable g.zTextName[] will identify the specific XSQL and
65 ** DB values that were running when the crash occurred.
73 #define ISSPACE(X) isspace((unsigned char)(X))
74 #define ISDIGIT(X) isdigit((unsigned char)(X))
82 #ifdef SQLITE_OSS_FUZZ
84 # if !defined(_MSC_VER)
90 typedef unsigned char uint8_t;
94 ** Files in the virtual file system.
96 typedef struct VFile VFile
;
98 char *zFilename
; /* Filename. NULL for delete-on-close. From malloc() */
99 int sz
; /* Size of the file in bytes */
100 int nRef
; /* Number of references to this file */
101 unsigned char *a
; /* Content of the file. From malloc() */
103 typedef struct VHandle VHandle
;
105 sqlite3_file base
; /* Base class. Must be first */
106 VFile
*pVFile
; /* The underlying file */
110 ** The value of a database file template, or of an SQL script
112 typedef struct Blob Blob
;
114 Blob
*pNext
; /* Next in a list */
115 int id
; /* Id of this Blob */
116 int seq
; /* Sequence number */
117 int sz
; /* Size of this Blob in bytes */
118 unsigned char a
[1]; /* Blob content. Extra space allocated as needed. */
122 ** Maximum number of files in the in-memory virtual filesystem.
127 ** Maximum allowed file size
129 #define MX_FILE_SZ 10000000
132 ** All global variables are gathered into the "g" singleton.
134 static struct GlobalVars
{
135 const char *zArgv0
; /* Name of program */
136 VFile aFile
[MX_FILE
]; /* The virtual filesystem */
137 int nDb
; /* Number of template databases */
138 Blob
*pFirstDb
; /* Content of first template database */
139 int nSql
; /* Number of SQL scripts */
140 Blob
*pFirstSql
; /* First SQL script */
141 unsigned int uRandom
; /* Seed for the SQLite PRNG */
142 char zTestName
[100]; /* Name of current test */
146 ** Print an error message and quit.
148 static void fatalError(const char *zFormat
, ...){
150 if( g
.zTestName
[0] ){
151 fprintf(stderr
, "%s (%s): ", g
.zArgv0
, g
.zTestName
);
153 fprintf(stderr
, "%s: ", g
.zArgv0
);
155 va_start(ap
, zFormat
);
156 vfprintf(stderr
, zFormat
, ap
);
158 fprintf(stderr
, "\n");
166 static void timeoutHandler(int NotUsed
){
168 fatalError("timeout\n");
173 ** Set the an alarm to go off after N seconds. Disable the alarm
176 static void setAlarm(int N
){
184 #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
186 ** This an SQL progress handler. After an SQL statement has run for
187 ** many steps, we want to interrupt it. This guards against infinite
188 ** loops from recursive common table expressions.
190 ** *pVdbeLimitFlag is true if the --limit-vdbe command-line option is used.
191 ** In that case, hitting the progress handler is a fatal error.
193 static int progressHandler(void *pVdbeLimitFlag
){
194 if( *(int*)pVdbeLimitFlag
) fatalError("too many VDBE cycles");
200 ** Reallocate memory. Show and error and quit if unable.
202 static void *safe_realloc(void *pOld
, int szNew
){
203 void *pNew
= realloc(pOld
, szNew
<=0 ? 1 : szNew
);
204 if( pNew
==0 ) fatalError("unable to realloc for %d bytes", szNew
);
209 ** Initialize the virtual file system.
211 static void formatVfs(void){
213 for(i
=0; i
<MX_FILE
; i
++){
215 g
.aFile
[i
].zFilename
= 0;
223 ** Erase all information in the virtual file system.
225 static void reformatVfs(void){
227 for(i
=0; i
<MX_FILE
; i
++){
228 if( g
.aFile
[i
].sz
<0 ) continue;
229 if( g
.aFile
[i
].zFilename
){
230 free(g
.aFile
[i
].zFilename
);
231 g
.aFile
[i
].zFilename
= 0;
233 if( g
.aFile
[i
].nRef
>0 ){
234 fatalError("file %d still open. nRef=%d", i
, g
.aFile
[i
].nRef
);
244 ** Find a VFile by name
246 static VFile
*findVFile(const char *zName
){
248 if( zName
==0 ) return 0;
249 for(i
=0; i
<MX_FILE
; i
++){
250 if( g
.aFile
[i
].zFilename
==0 ) continue;
251 if( strcmp(g
.aFile
[i
].zFilename
, zName
)==0 ) return &g
.aFile
[i
];
257 ** Find a VFile by name. Create it if it does not already exist and
258 ** initialize it to the size and content given.
260 ** Return NULL only if the filesystem is full.
262 static VFile
*createVFile(const char *zName
, int sz
, unsigned char *pData
){
263 VFile
*pNew
= findVFile(zName
);
265 if( pNew
) return pNew
;
266 for(i
=0; i
<MX_FILE
&& g
.aFile
[i
].sz
>=0; i
++){}
267 if( i
>=MX_FILE
) return 0;
270 int nName
= (int)strlen(zName
)+1;
271 pNew
->zFilename
= safe_realloc(0, nName
);
272 memcpy(pNew
->zFilename
, zName
, nName
);
278 pNew
->a
= safe_realloc(0, sz
);
279 if( sz
>0 ) memcpy(pNew
->a
, pData
, sz
);
285 ** Implementation of the "readfile(X)" SQL function. The entire content
286 ** of the file named X is read and returned as a BLOB. NULL is returned
287 ** if the file does not exist or is unreadable.
289 static void readfileFunc(
290 sqlite3_context
*context
,
299 zName
= (const char*)sqlite3_value_text(argv
[0]);
300 if( zName
==0 ) return;
301 in
= fopen(zName
, "rb");
303 fseek(in
, 0, SEEK_END
);
306 pBuf
= sqlite3_malloc64( nIn
);
307 if( pBuf
&& 1==fread(pBuf
, nIn
, 1, in
) ){
308 sqlite3_result_blob(context
, pBuf
, nIn
, sqlite3_free
);
316 ** Implementation of the "writefile(X,Y)" SQL function. The argument Y
317 ** is written into file X. The number of bytes written is returned. Or
318 ** NULL is returned if something goes wrong, such as being unable to open
319 ** file X for writing.
321 static void writefileFunc(
322 sqlite3_context
*context
,
332 zFile
= (const char*)sqlite3_value_text(argv
[0]);
333 if( zFile
==0 ) return;
334 out
= fopen(zFile
, "wb");
336 z
= (const char*)sqlite3_value_blob(argv
[1]);
340 rc
= fwrite(z
, 1, sqlite3_value_bytes(argv
[1]), out
);
343 sqlite3_result_int64(context
, rc
);
348 ** Load a list of Blob objects from the database
350 static void blobListLoadFromDb(
351 sqlite3
*db
, /* Read from this database */
352 const char *zSql
, /* Query used to extract the blobs */
353 int onlyId
, /* Only load where id is this value */
354 int *pN
, /* OUT: Write number of blobs loaded here */
355 Blob
**ppList
/* OUT: Write the head of the blob list here */
365 z2
= sqlite3_mprintf("%s WHERE rowid=%d", zSql
, onlyId
);
367 z2
= sqlite3_mprintf("%s", zSql
);
369 rc
= sqlite3_prepare_v2(db
, z2
, -1, &pStmt
, 0);
371 if( rc
) fatalError("%s", sqlite3_errmsg(db
));
374 while( SQLITE_ROW
==sqlite3_step(pStmt
) ){
375 int sz
= sqlite3_column_bytes(pStmt
, 1);
376 Blob
*pNew
= safe_realloc(0, sizeof(*pNew
)+sz
);
377 pNew
->id
= sqlite3_column_int(pStmt
, 0);
381 memcpy(pNew
->a
, sqlite3_column_blob(pStmt
,1), sz
);
386 sqlite3_finalize(pStmt
);
388 *ppList
= head
.pNext
;
392 ** Free a list of Blob objects
394 static void blobListFree(Blob
*p
){
404 /* Return the current wall-clock time */
405 static sqlite3_int64
timeOfDay(void){
406 static sqlite3_vfs
*clockVfs
= 0;
408 if( clockVfs
==0 ) clockVfs
= sqlite3_vfs_find(0);
409 if( clockVfs
->iVersion
>=1 && clockVfs
->xCurrentTimeInt64
!=0 ){
410 clockVfs
->xCurrentTimeInt64(clockVfs
, &t
);
413 clockVfs
->xCurrentTime(clockVfs
, &r
);
414 t
= (sqlite3_int64
)(r
*86400000.0);
419 /* Methods for the VHandle object
421 static int inmemClose(sqlite3_file
*pFile
){
422 VHandle
*p
= (VHandle
*)pFile
;
423 VFile
*pVFile
= p
->pVFile
;
425 if( pVFile
->nRef
==0 && pVFile
->zFilename
==0 ){
432 static int inmemRead(
433 sqlite3_file
*pFile
, /* Read from this open file */
434 void *pData
, /* Store content in this buffer */
435 int iAmt
, /* Bytes of content */
436 sqlite3_int64 iOfst
/* Start reading here */
438 VHandle
*pHandle
= (VHandle
*)pFile
;
439 VFile
*pVFile
= pHandle
->pVFile
;
440 if( iOfst
<0 || iOfst
>=pVFile
->sz
){
441 memset(pData
, 0, iAmt
);
442 return SQLITE_IOERR_SHORT_READ
;
444 if( iOfst
+iAmt
>pVFile
->sz
){
445 memset(pData
, 0, iAmt
);
446 iAmt
= (int)(pVFile
->sz
- iOfst
);
447 memcpy(pData
, pVFile
->a
, iAmt
);
448 return SQLITE_IOERR_SHORT_READ
;
450 memcpy(pData
, pVFile
->a
+ iOfst
, iAmt
);
453 static int inmemWrite(
454 sqlite3_file
*pFile
, /* Write to this file */
455 const void *pData
, /* Content to write */
456 int iAmt
, /* bytes to write */
457 sqlite3_int64 iOfst
/* Start writing here */
459 VHandle
*pHandle
= (VHandle
*)pFile
;
460 VFile
*pVFile
= pHandle
->pVFile
;
461 if( iOfst
+iAmt
> pVFile
->sz
){
462 if( iOfst
+iAmt
>= MX_FILE_SZ
){
465 pVFile
->a
= safe_realloc(pVFile
->a
, (int)(iOfst
+iAmt
));
466 if( iOfst
> pVFile
->sz
){
467 memset(pVFile
->a
+ pVFile
->sz
, 0, (int)(iOfst
- pVFile
->sz
));
469 pVFile
->sz
= (int)(iOfst
+ iAmt
);
471 memcpy(pVFile
->a
+ iOfst
, pData
, iAmt
);
474 static int inmemTruncate(sqlite3_file
*pFile
, sqlite3_int64 iSize
){
475 VHandle
*pHandle
= (VHandle
*)pFile
;
476 VFile
*pVFile
= pHandle
->pVFile
;
477 if( pVFile
->sz
>iSize
&& iSize
>=0 ) pVFile
->sz
= (int)iSize
;
480 static int inmemSync(sqlite3_file
*pFile
, int flags
){
483 static int inmemFileSize(sqlite3_file
*pFile
, sqlite3_int64
*pSize
){
484 *pSize
= ((VHandle
*)pFile
)->pVFile
->sz
;
487 static int inmemLock(sqlite3_file
*pFile
, int type
){
490 static int inmemUnlock(sqlite3_file
*pFile
, int type
){
493 static int inmemCheckReservedLock(sqlite3_file
*pFile
, int *pOut
){
497 static int inmemFileControl(sqlite3_file
*pFile
, int op
, void *pArg
){
498 return SQLITE_NOTFOUND
;
500 static int inmemSectorSize(sqlite3_file
*pFile
){
503 static int inmemDeviceCharacteristics(sqlite3_file
*pFile
){
505 SQLITE_IOCAP_SAFE_APPEND
|
506 SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
|
507 SQLITE_IOCAP_POWERSAFE_OVERWRITE
;
511 /* Method table for VHandle
513 static sqlite3_io_methods VHandleMethods
= {
515 /* xClose */ inmemClose
,
516 /* xRead */ inmemRead
,
517 /* xWrite */ inmemWrite
,
518 /* xTruncate */ inmemTruncate
,
519 /* xSync */ inmemSync
,
520 /* xFileSize */ inmemFileSize
,
521 /* xLock */ inmemLock
,
522 /* xUnlock */ inmemUnlock
,
523 /* xCheck... */ inmemCheckReservedLock
,
524 /* xFileCtrl */ inmemFileControl
,
525 /* xSectorSz */ inmemSectorSize
,
526 /* xDevchar */ inmemDeviceCharacteristics
,
536 ** Open a new file in the inmem VFS. All files are anonymous and are
539 static int inmemOpen(
541 const char *zFilename
,
546 VFile
*pVFile
= createVFile(zFilename
, 0, (unsigned char*)"");
547 VHandle
*pHandle
= (VHandle
*)pFile
;
551 pHandle
->pVFile
= pVFile
;
553 pFile
->pMethods
= &VHandleMethods
;
554 if( pOutFlags
) *pOutFlags
= openFlags
;
559 ** Delete a file by name
561 static int inmemDelete(
563 const char *zFilename
,
566 VFile
*pVFile
= findVFile(zFilename
);
567 if( pVFile
==0 ) return SQLITE_OK
;
568 if( pVFile
->nRef
==0 ){
569 free(pVFile
->zFilename
);
570 pVFile
->zFilename
= 0;
576 return SQLITE_IOERR_DELETE
;
579 /* Check for the existance of a file
581 static int inmemAccess(
583 const char *zFilename
,
587 VFile
*pVFile
= findVFile(zFilename
);
588 *pResOut
= pVFile
!=0;
592 /* Get the canonical pathname for a file
594 static int inmemFullPathname(
596 const char *zFilename
,
600 sqlite3_snprintf(nOut
, zOut
, "%s", zFilename
);
604 /* Always use the same random see, for repeatability.
606 static int inmemRandomness(sqlite3_vfs
*NotUsed
, int nBuf
, char *zBuf
){
607 memset(zBuf
, 0, nBuf
);
608 memcpy(zBuf
, &g
.uRandom
, nBuf
<sizeof(g
.uRandom
) ? nBuf
: sizeof(g
.uRandom
));
613 ** Register the VFS that reads from the g.aFile[] set of files.
615 static void inmemVfsRegister(int makeDefault
){
616 static sqlite3_vfs inmemVfs
;
617 sqlite3_vfs
*pDefault
= sqlite3_vfs_find(0);
618 inmemVfs
.iVersion
= 3;
619 inmemVfs
.szOsFile
= sizeof(VHandle
);
620 inmemVfs
.mxPathname
= 200;
621 inmemVfs
.zName
= "inmem";
622 inmemVfs
.xOpen
= inmemOpen
;
623 inmemVfs
.xDelete
= inmemDelete
;
624 inmemVfs
.xAccess
= inmemAccess
;
625 inmemVfs
.xFullPathname
= inmemFullPathname
;
626 inmemVfs
.xRandomness
= inmemRandomness
;
627 inmemVfs
.xSleep
= pDefault
->xSleep
;
628 inmemVfs
.xCurrentTimeInt64
= pDefault
->xCurrentTimeInt64
;
629 sqlite3_vfs_register(&inmemVfs
, makeDefault
);
633 ** Allowed values for the runFlags parameter to runSql()
635 #define SQL_TRACE 0x0001 /* Print each SQL statement as it is prepared */
636 #define SQL_OUTPUT 0x0002 /* Show the SQL output */
639 ** Run multiple commands of SQL. Similar to sqlite3_exec(), but does not
640 ** stop if an error is encountered.
642 static void runSql(sqlite3
*db
, const char *zSql
, unsigned runFlags
){
646 while( zSql
&& zSql
[0] ){
649 sqlite3_prepare_v2(db
, zSql
, -1, &pStmt
, &zMore
);
650 if( zMore
==zSql
) break;
651 if( runFlags
& SQL_TRACE
){
652 const char *z
= zSql
;
654 while( z
<zMore
&& ISSPACE(z
[0]) ) z
++;
655 n
= (int)(zMore
- z
);
656 while( n
>0 && ISSPACE(z
[n
-1]) ) n
--;
659 printf("TRACE: %.*s (error: %s)\n", n
, z
, sqlite3_errmsg(db
));
661 printf("TRACE: %.*s\n", n
, z
);
666 if( (runFlags
& SQL_OUTPUT
)==0 ){
667 while( SQLITE_ROW
==sqlite3_step(pStmt
) ){}
670 while( SQLITE_ROW
==sqlite3_step(pStmt
) ){
673 nCol
= sqlite3_column_count(pStmt
);
675 printf("--------------------------------------------\n");
677 for(i
=0; i
<nCol
; i
++){
678 int eType
= sqlite3_column_type(pStmt
,i
);
679 printf("%s = ", sqlite3_column_name(pStmt
,i
));
685 case SQLITE_INTEGER
: {
686 printf("INT %s\n", sqlite3_column_text(pStmt
,i
));
690 printf("FLOAT %s\n", sqlite3_column_text(pStmt
,i
));
694 printf("TEXT [%s]\n", sqlite3_column_text(pStmt
,i
));
698 printf("BLOB (%d bytes)\n", sqlite3_column_bytes(pStmt
,i
));
705 sqlite3_finalize(pStmt
);
711 ** Rebuild the database file.
713 ** (1) Remove duplicate entries
714 ** (2) Put all entries in order
717 static void rebuild_database(sqlite3
*db
){
719 rc
= sqlite3_exec(db
,
721 "CREATE TEMP TABLE dbx AS SELECT DISTINCT dbcontent FROM db;\n"
723 "INSERT INTO db(dbid, dbcontent) "
724 " SELECT NULL, dbcontent FROM dbx ORDER BY 2;\n"
726 "CREATE TEMP TABLE sx AS SELECT DISTINCT sqltext FROM xsql;\n"
727 "DELETE FROM xsql;\n"
728 "INSERT INTO xsql(sqlid,sqltext) "
729 " SELECT NULL, sqltext FROM sx ORDER BY 2;\n"
732 "PRAGMA page_size=1024;\n"
733 "VACUUM;\n", 0, 0, 0);
734 if( rc
) fatalError("cannot rebuild: %s", sqlite3_errmsg(db
));
738 ** Return the value of a hexadecimal digit. Return -1 if the input
739 ** is not a hex digit.
741 static int hexDigitValue(char c
){
742 if( c
>='0' && c
<='9' ) return c
- '0';
743 if( c
>='a' && c
<='f' ) return c
- 'a' + 10;
744 if( c
>='A' && c
<='F' ) return c
- 'A' + 10;
749 ** Interpret zArg as an integer value, possibly with suffixes.
751 static int integerValue(const char *zArg
){
753 static const struct { char *zSuffix
; int iMult
; } aMult
[] = {
755 { "MiB", 1024*1024 },
756 { "GiB", 1024*1024*1024 },
759 { "GB", 1000000000 },
769 }else if( zArg
[0]=='+' ){
772 if( zArg
[0]=='0' && zArg
[1]=='x' ){
775 while( (x
= hexDigitValue(zArg
[0]))>=0 ){
780 while( ISDIGIT(zArg
[0]) ){
781 v
= v
*10 + zArg
[0] - '0';
785 for(i
=0; i
<sizeof(aMult
)/sizeof(aMult
[0]); i
++){
786 if( sqlite3_stricmp(aMult
[i
].zSuffix
, zArg
)==0 ){
791 if( v
>0x7fffffff ) fatalError("parameter too large - max 2147483648");
792 return (int)(isNeg
? -v
: v
);
796 ** Print sketchy documentation for this utility program
798 static void showHelp(void){
799 printf("Usage: %s [options] SOURCE-DB ?ARGS...?\n", g
.zArgv0
);
801 "Read databases and SQL scripts from SOURCE-DB and execute each script against\n"
802 "each database, checking for crashes and memory leaks.\n"
804 " --cell-size-check Set the PRAGMA cell_size_check=ON\n"
805 " --dbid N Use only the database where dbid=N\n"
806 " --export-db DIR Write databases to files(s) in DIR. Works with --dbid\n"
807 " --export-sql DIR Write SQL to file(s) in DIR. Also works with --sqlid\n"
808 " --help Show this help text\n"
809 " --info Show information about SOURCE-DB w/o running tests\n"
810 " --limit-mem N Limit memory used by test SQLite instance to N bytes\n"
811 " --limit-vdbe Panic if any test runs for more than 100,000 cycles\n"
812 " --load-sql ARGS... Load SQL scripts fron files into SOURCE-DB\n"
813 " --load-db ARGS... Load template databases from files into SOURCE_DB\n"
814 " -m TEXT Add a description to the database\n"
815 " --native-vfs Use the native VFS for initially empty database files\n"
816 " --native-malloc Turn off MEMSYS3/5 and Lookaside\n"
817 " --oss-fuzz Enable OSS-FUZZ testing\n"
818 " --prng-seed N Seed value for the PRGN inside of SQLite\n"
819 " -q|--quiet Reduced output\n"
820 " --rebuild Rebuild and vacuum the database file\n"
821 " --result-trace Show the results of each SQL command\n"
822 " --sqlid N Use only SQL where sqlid=N\n"
823 " --timeout N Abort if any single test needs more than N seconds\n"
824 " -v|--verbose Increased output. Repeat for more output.\n"
828 int main(int argc
, char **argv
){
829 sqlite3_int64 iBegin
; /* Start time of this program */
830 int quietFlag
= 0; /* True if --quiet or -q */
831 int verboseFlag
= 0; /* True if --verbose or -v */
832 char *zInsSql
= 0; /* SQL statement for --load-db or --load-sql */
833 int iFirstInsArg
= 0; /* First argv[] for --load-db or --load-sql */
834 sqlite3
*db
= 0; /* The open database connection */
835 sqlite3_stmt
*pStmt
; /* A prepared statement */
836 int rc
; /* Result code from SQLite interface calls */
837 Blob
*pSql
; /* For looping over SQL scripts */
838 Blob
*pDb
; /* For looping over template databases */
839 int i
; /* Loop index for the argv[] loop */
840 int onlySqlid
= -1; /* --sqlid */
841 int onlyDbid
= -1; /* --dbid */
842 int nativeFlag
= 0; /* --native-vfs */
843 int rebuildFlag
= 0; /* --rebuild */
844 int vdbeLimitFlag
= 0; /* --limit-vdbe */
845 int infoFlag
= 0; /* --info */
846 int timeoutTest
= 0; /* undocumented --timeout-test flag */
847 int runFlags
= 0; /* Flags sent to runSql() */
848 char *zMsg
= 0; /* Add this message */
849 int nSrcDb
= 0; /* Number of source databases */
850 char **azSrcDb
= 0; /* Array of source database names */
851 int iSrcDb
; /* Loop over all source databases */
852 int nTest
= 0; /* Total number of tests performed */
853 char *zDbName
= ""; /* Appreviated name of a source database */
854 const char *zFailCode
= 0; /* Value of the TEST_FAILURE env variable */
855 int cellSzCkFlag
= 0; /* --cell-size-check */
856 int sqlFuzz
= 0; /* True for SQL fuzz. False for DB fuzz */
857 int iTimeout
= 120; /* Default 120-second timeout */
858 int nMem
= 0; /* Memory limit */
859 int nMemThisDb
= 0; /* Memory limit set by the CONFIG table */
860 char *zExpDb
= 0; /* Write Databases to files in this directory */
861 char *zExpSql
= 0; /* Write SQL to files in this directory */
862 void *pHeap
= 0; /* Heap for use by SQLite */
863 int ossFuzz
= 0; /* enable OSS-FUZZ testing */
864 int ossFuzzThisDb
= 0; /* ossFuzz value for this particular database */
865 int nativeMalloc
= 0; /* Turn off MEMSYS3/5 and lookaside if true */
866 sqlite3_vfs
*pDfltVfs
; /* The default VFS */
867 int openFlags4Data
; /* Flags for sqlite3_open_v2() */
869 iBegin
= timeOfDay();
871 signal(SIGALRM
, timeoutHandler
);
874 openFlags4Data
= SQLITE_OPEN_READONLY
;
875 zFailCode
= getenv("TEST_FAILURE");
876 pDfltVfs
= sqlite3_vfs_find(0);
878 for(i
=1; i
<argc
; i
++){
879 const char *z
= argv
[i
];
883 if( strcmp(z
,"cell-size-check")==0 ){
886 if( strcmp(z
,"dbid")==0 ){
887 if( i
>=argc
-1 ) fatalError("missing arguments on %s", argv
[i
]);
888 onlyDbid
= integerValue(argv
[++i
]);
890 if( strcmp(z
,"export-db")==0 ){
891 if( i
>=argc
-1 ) fatalError("missing arguments on %s", argv
[i
]);
894 if( strcmp(z
,"export-sql")==0 ){
895 if( i
>=argc
-1 ) fatalError("missing arguments on %s", argv
[i
]);
898 if( strcmp(z
,"help")==0 ){
902 if( strcmp(z
,"info")==0 ){
905 if( strcmp(z
,"limit-mem")==0 ){
906 #if !defined(SQLITE_ENABLE_MEMSYS3) && !defined(SQLITE_ENABLE_MEMSYS5)
907 fatalError("the %s option requires -DSQLITE_ENABLE_MEMSYS5 or _MEMSYS3",
910 if( i
>=argc
-1 ) fatalError("missing arguments on %s", argv
[i
]);
911 nMem
= integerValue(argv
[++i
]);
914 if( strcmp(z
,"limit-vdbe")==0 ){
917 if( strcmp(z
,"load-sql")==0 ){
918 zInsSql
= "INSERT INTO xsql(sqltext)VALUES(CAST(readfile(?1) AS text))";
920 openFlags4Data
= SQLITE_OPEN_READWRITE
|SQLITE_OPEN_CREATE
;
923 if( strcmp(z
,"load-db")==0 ){
924 zInsSql
= "INSERT INTO db(dbcontent) VALUES(readfile(?1))";
926 openFlags4Data
= SQLITE_OPEN_READWRITE
|SQLITE_OPEN_CREATE
;
929 if( strcmp(z
,"m")==0 ){
930 if( i
>=argc
-1 ) fatalError("missing arguments on %s", argv
[i
]);
932 openFlags4Data
= SQLITE_OPEN_READWRITE
|SQLITE_OPEN_CREATE
;
934 if( strcmp(z
,"native-malloc")==0 ){
937 if( strcmp(z
,"native-vfs")==0 ){
940 if( strcmp(z
,"oss-fuzz")==0 ){
943 if( strcmp(z
,"prng-seed")==0 ){
944 if( i
>=argc
-1 ) fatalError("missing arguments on %s", argv
[i
]);
945 g
.uRandom
= atoi(argv
[++i
]);
947 if( strcmp(z
,"quiet")==0 || strcmp(z
,"q")==0 ){
951 if( strcmp(z
,"rebuild")==0 ){
953 openFlags4Data
= SQLITE_OPEN_READWRITE
;
955 if( strcmp(z
,"result-trace")==0 ){
956 runFlags
|= SQL_OUTPUT
;
958 if( strcmp(z
,"sqlid")==0 ){
959 if( i
>=argc
-1 ) fatalError("missing arguments on %s", argv
[i
]);
960 onlySqlid
= integerValue(argv
[++i
]);
962 if( strcmp(z
,"timeout")==0 ){
963 if( i
>=argc
-1 ) fatalError("missing arguments on %s", argv
[i
]);
964 iTimeout
= integerValue(argv
[++i
]);
966 if( strcmp(z
,"timeout-test")==0 ){
969 fatalError("timeout is not available on non-unix systems");
972 if( strcmp(z
,"verbose")==0 || strcmp(z
,"v")==0 ){
975 if( verboseFlag
>1 ) runFlags
|= SQL_TRACE
;
978 fatalError("unknown option: %s", argv
[i
]);
982 azSrcDb
= safe_realloc(azSrcDb
, nSrcDb
*sizeof(azSrcDb
[0]));
983 azSrcDb
[nSrcDb
-1] = argv
[i
];
986 if( nSrcDb
==0 ) fatalError("no source database specified");
989 fatalError("cannot change the description of more than one database");
992 fatalError("cannot import into more than one database");
996 /* Process each source database separately */
997 for(iSrcDb
=0; iSrcDb
<nSrcDb
; iSrcDb
++){
998 rc
= sqlite3_open_v2(azSrcDb
[iSrcDb
], &db
,
999 openFlags4Data
, pDfltVfs
->zName
);
1001 fatalError("cannot open source database %s - %s",
1002 azSrcDb
[iSrcDb
], sqlite3_errmsg(db
));
1005 /* Print the description, if there is one */
1008 zDbName
= azSrcDb
[iSrcDb
];
1009 i
= (int)strlen(zDbName
) - 1;
1010 while( i
>0 && zDbName
[i
-1]!='/' && zDbName
[i
-1]!='\\' ){ i
--; }
1012 sqlite3_prepare_v2(db
, "SELECT msg FROM readme", -1, &pStmt
, 0);
1013 if( pStmt
&& sqlite3_step(pStmt
)==SQLITE_ROW
){
1014 printf("%s: %s", zDbName
, sqlite3_column_text(pStmt
,0));
1016 printf("%s: (empty \"readme\")", zDbName
);
1018 sqlite3_finalize(pStmt
);
1019 sqlite3_prepare_v2(db
, "SELECT count(*) FROM db", -1, &pStmt
, 0);
1021 && sqlite3_step(pStmt
)==SQLITE_ROW
1022 && (n
= sqlite3_column_int(pStmt
,0))>0
1024 printf(" - %d DBs", n
);
1026 sqlite3_finalize(pStmt
);
1027 sqlite3_prepare_v2(db
, "SELECT count(*) FROM xsql", -1, &pStmt
, 0);
1029 && sqlite3_step(pStmt
)==SQLITE_ROW
1030 && (n
= sqlite3_column_int(pStmt
,0))>0
1032 printf(" - %d scripts", n
);
1034 sqlite3_finalize(pStmt
);
1040 rc
= sqlite3_exec(db
,
1041 "CREATE TABLE IF NOT EXISTS db(\n"
1042 " dbid INTEGER PRIMARY KEY, -- database id\n"
1043 " dbcontent BLOB -- database disk file image\n"
1045 "CREATE TABLE IF NOT EXISTS xsql(\n"
1046 " sqlid INTEGER PRIMARY KEY, -- SQL script id\n"
1047 " sqltext TEXT -- Text of SQL statements to run\n"
1049 "CREATE TABLE IF NOT EXISTS readme(\n"
1050 " msg TEXT -- Human-readable description of this file\n"
1052 if( rc
) fatalError("cannot create schema: %s", sqlite3_errmsg(db
));
1055 zSql
= sqlite3_mprintf(
1056 "DELETE FROM readme; INSERT INTO readme(msg) VALUES(%Q)", zMsg
);
1057 rc
= sqlite3_exec(db
, zSql
, 0, 0, 0);
1059 if( rc
) fatalError("cannot change description: %s", sqlite3_errmsg(db
));
1061 ossFuzzThisDb
= ossFuzz
;
1063 /* If the CONFIG(name,value) table exists, read db-specific settings
1064 ** from that table */
1065 if( sqlite3_table_column_metadata(db
,0,"config",0,0,0,0,0,0)==SQLITE_OK
){
1066 rc
= sqlite3_prepare_v2(db
, "SELECT name, value FROM config",
1068 if( rc
) fatalError("cannot prepare query of CONFIG table: %s",
1069 sqlite3_errmsg(db
));
1070 while( SQLITE_ROW
==sqlite3_step(pStmt
) ){
1071 const char *zName
= (const char *)sqlite3_column_text(pStmt
,0);
1072 if( zName
==0 ) continue;
1073 if( strcmp(zName
, "oss-fuzz")==0 ){
1074 ossFuzzThisDb
= sqlite3_column_int(pStmt
,1);
1075 if( verboseFlag
) printf("Config: oss-fuzz=%d\n", ossFuzzThisDb
);
1077 if( strcmp(zName
, "limit-mem")==0 && !nativeMalloc
){
1078 #if !defined(SQLITE_ENABLE_MEMSYS3) && !defined(SQLITE_ENABLE_MEMSYS5)
1079 fatalError("the limit-mem option requires -DSQLITE_ENABLE_MEMSYS5"
1082 nMemThisDb
= sqlite3_column_int(pStmt
,1);
1083 if( verboseFlag
) printf("Config: limit-mem=%d\n", nMemThisDb
);
1087 sqlite3_finalize(pStmt
);
1091 sqlite3_create_function(db
, "readfile", 1, SQLITE_UTF8
, 0,
1092 readfileFunc
, 0, 0);
1093 rc
= sqlite3_prepare_v2(db
, zInsSql
, -1, &pStmt
, 0);
1094 if( rc
) fatalError("cannot prepare statement [%s]: %s",
1095 zInsSql
, sqlite3_errmsg(db
));
1096 rc
= sqlite3_exec(db
, "BEGIN", 0, 0, 0);
1097 if( rc
) fatalError("cannot start a transaction");
1098 for(i
=iFirstInsArg
; i
<argc
; i
++){
1099 sqlite3_bind_text(pStmt
, 1, argv
[i
], -1, SQLITE_STATIC
);
1100 sqlite3_step(pStmt
);
1101 rc
= sqlite3_reset(pStmt
);
1102 if( rc
) fatalError("insert failed for %s", argv
[i
]);
1104 sqlite3_finalize(pStmt
);
1105 rc
= sqlite3_exec(db
, "COMMIT", 0, 0, 0);
1106 if( rc
) fatalError("cannot commit the transaction: %s",
1107 sqlite3_errmsg(db
));
1108 rebuild_database(db
);
1112 rc
= sqlite3_exec(db
, "PRAGMA query_only=1;", 0, 0, 0);
1113 if( rc
) fatalError("cannot set database to query-only");
1114 if( zExpDb
!=0 || zExpSql
!=0 ){
1115 sqlite3_create_function(db
, "writefile", 2, SQLITE_UTF8
, 0,
1116 writefileFunc
, 0, 0);
1119 "SELECT writefile(printf('%s/db%06d.db',?1,dbid),dbcontent),"
1120 " dbid, printf('%s/db%06d.db',?1,dbid), length(dbcontent)"
1121 " FROM db WHERE ?2<0 OR dbid=?2;";
1122 rc
= sqlite3_prepare_v2(db
, zExDb
, -1, &pStmt
, 0);
1123 if( rc
) fatalError("cannot prepare statement [%s]: %s",
1124 zExDb
, sqlite3_errmsg(db
));
1125 sqlite3_bind_text64(pStmt
, 1, zExpDb
, strlen(zExpDb
),
1126 SQLITE_STATIC
, SQLITE_UTF8
);
1127 sqlite3_bind_int(pStmt
, 2, onlyDbid
);
1128 while( sqlite3_step(pStmt
)==SQLITE_ROW
){
1129 printf("write db-%d (%d bytes) into %s\n",
1130 sqlite3_column_int(pStmt
,1),
1131 sqlite3_column_int(pStmt
,3),
1132 sqlite3_column_text(pStmt
,2));
1134 sqlite3_finalize(pStmt
);
1137 const char *zExSql
=
1138 "SELECT writefile(printf('%s/sql%06d.txt',?1,sqlid),sqltext),"
1139 " sqlid, printf('%s/sql%06d.txt',?1,sqlid), length(sqltext)"
1140 " FROM xsql WHERE ?2<0 OR sqlid=?2;";
1141 rc
= sqlite3_prepare_v2(db
, zExSql
, -1, &pStmt
, 0);
1142 if( rc
) fatalError("cannot prepare statement [%s]: %s",
1143 zExSql
, sqlite3_errmsg(db
));
1144 sqlite3_bind_text64(pStmt
, 1, zExpSql
, strlen(zExpSql
),
1145 SQLITE_STATIC
, SQLITE_UTF8
);
1146 sqlite3_bind_int(pStmt
, 2, onlySqlid
);
1147 while( sqlite3_step(pStmt
)==SQLITE_ROW
){
1148 printf("write sql-%d (%d bytes) into %s\n",
1149 sqlite3_column_int(pStmt
,1),
1150 sqlite3_column_int(pStmt
,3),
1151 sqlite3_column_text(pStmt
,2));
1153 sqlite3_finalize(pStmt
);
1159 /* Load all SQL script content and all initial database images from the
1162 blobListLoadFromDb(db
, "SELECT sqlid, sqltext FROM xsql", onlySqlid
,
1163 &g
.nSql
, &g
.pFirstSql
);
1164 if( g
.nSql
==0 ) fatalError("need at least one SQL script");
1165 blobListLoadFromDb(db
, "SELECT dbid, dbcontent FROM db", onlyDbid
,
1166 &g
.nDb
, &g
.pFirstDb
);
1168 g
.pFirstDb
= safe_realloc(0, sizeof(Blob
));
1169 memset(g
.pFirstDb
, 0, sizeof(Blob
));
1171 g
.pFirstDb
->seq
= 0;
1176 /* Print the description, if there is one */
1178 zDbName
= azSrcDb
[iSrcDb
];
1179 i
= (int)strlen(zDbName
) - 1;
1180 while( i
>0 && zDbName
[i
-1]!='/' && zDbName
[i
-1]!='\\' ){ i
--; }
1182 sqlite3_prepare_v2(db
, "SELECT msg FROM readme", -1, &pStmt
, 0);
1183 if( pStmt
&& sqlite3_step(pStmt
)==SQLITE_ROW
){
1184 printf("%s: %s\n", zDbName
, sqlite3_column_text(pStmt
,0));
1186 sqlite3_finalize(pStmt
);
1189 /* Rebuild the database, if requested */
1192 printf("%s: rebuilding... ", zDbName
);
1195 rebuild_database(db
);
1196 if( !quietFlag
) printf("done\n");
1199 /* Close the source database. Verify that no SQLite memory allocations are
1203 if( sqlite3_memory_used()>0 ){
1204 fatalError("SQLite has memory in use before the start of testing");
1207 /* Limit available memory, if requested */
1209 if( nMemThisDb
>0 && !nativeMalloc
){
1210 pHeap
= realloc(pHeap
, nMemThisDb
);
1212 fatalError("failed to allocate %d bytes of heap memory", nMem
);
1214 sqlite3_config(SQLITE_CONFIG_HEAP
, pHeap
, nMemThisDb
, 128);
1217 /* Disable lookaside with the --native-malloc option */
1219 sqlite3_config(SQLITE_CONFIG_LOOKASIDE
, 0, 0);
1222 /* Reset the in-memory virtual filesystem */
1225 /* Run a test using each SQL script against each database.
1227 if( !verboseFlag
&& !quietFlag
) printf("%s:", zDbName
);
1228 for(pSql
=g
.pFirstSql
; pSql
; pSql
=pSql
->pNext
){
1229 for(pDb
=g
.pFirstDb
; pDb
; pDb
=pDb
->pNext
){
1231 const char *zVfs
= "inmem";
1232 sqlite3_snprintf(sizeof(g
.zTestName
), g
.zTestName
, "sqlid=%d,dbid=%d",
1235 printf("%s\n", g
.zTestName
);
1237 }else if( !quietFlag
){
1238 static int prevAmt
= -1;
1239 int idx
= pSql
->seq
*g
.nDb
+ pDb
->id
- 1;
1240 int amt
= idx
*10/(g
.nDb
*g
.nSql
);
1242 printf(" %d%%", amt
*10);
1247 createVFile("main.db", pDb
->sz
, pDb
->a
);
1248 sqlite3_randomness(0,0);
1249 if( ossFuzzThisDb
){
1250 #ifndef SQLITE_OSS_FUZZ
1251 fatalError("--oss-fuzz not supported: recompile"
1252 " with -DSQLITE_OSS_FUZZ");
1254 extern int LLVMFuzzerTestOneInput(const uint8_t*, size_t);
1255 LLVMFuzzerTestOneInput((const uint8_t*)pSql
->a
, (size_t)pSql
->sz
);
1258 openFlags
= SQLITE_OPEN_CREATE
| SQLITE_OPEN_READWRITE
;
1259 if( nativeFlag
&& pDb
->sz
==0 ){
1260 openFlags
|= SQLITE_OPEN_MEMORY
;
1263 rc
= sqlite3_open_v2("main.db", &db
, openFlags
, zVfs
);
1264 if( rc
) fatalError("cannot open inmem database");
1265 sqlite3_limit(db
, SQLITE_LIMIT_LENGTH
, 100000000);
1266 sqlite3_limit(db
, SQLITE_LIMIT_LIKE_PATTERN_LENGTH
, 50);
1267 if( cellSzCkFlag
) runSql(db
, "PRAGMA cell_size_check=ON", runFlags
);
1269 #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
1270 if( sqlFuzz
|| vdbeLimitFlag
){
1271 sqlite3_progress_handler(db
, 100000, progressHandler
,
1276 runSql(db
, (char*)pSql
->a
, runFlags
);
1277 }while( timeoutTest
);
1279 sqlite3_exec(db
, "PRAGMA temp_store_directory=''", 0, 0, 0);
1282 if( sqlite3_memory_used()>0 ){
1283 fatalError("memory leak: %lld bytes outstanding",
1284 sqlite3_memory_used());
1290 /* Simulate an error if the TEST_FAILURE environment variable is "5".
1291 ** This is used to verify that automated test script really do spot
1292 ** errors that occur in this test program.
1295 if( zFailCode
[0]=='5' && zFailCode
[1]==0 ){
1296 fatalError("simulated failure");
1297 }else if( zFailCode
[0]!=0 ){
1298 /* If TEST_FAILURE is something other than 5, just exit the test
1300 printf("\nExit early due to TEST_FAILURE being set\n");
1302 goto sourcedb_cleanup
;
1307 if( !quietFlag
&& !verboseFlag
){
1308 printf(" 100%% - %d tests\n", g
.nDb
*g
.nSql
);
1311 /* Clean up at the end of processing a single source database
1314 blobListFree(g
.pFirstSql
);
1315 blobListFree(g
.pFirstDb
);
1318 } /* End loop over all source databases */
1321 sqlite3_int64 iElapse
= timeOfDay() - iBegin
;
1322 printf("fuzzcheck: 0 errors out of %d tests in %d.%03d seconds\n"
1324 nTest
, (int)(iElapse
/1000), (int)(iElapse
%1000),
1325 sqlite3_libversion(), sqlite3_sourceid());