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;
409 clockVfs
= sqlite3_vfs_find(0);
410 if( clockVfs
==0 ) return 0;
412 if( clockVfs
->iVersion
>=1 && clockVfs
->xCurrentTimeInt64
!=0 ){
413 clockVfs
->xCurrentTimeInt64(clockVfs
, &t
);
416 clockVfs
->xCurrentTime(clockVfs
, &r
);
417 t
= (sqlite3_int64
)(r
*86400000.0);
422 /* Methods for the VHandle object
424 static int inmemClose(sqlite3_file
*pFile
){
425 VHandle
*p
= (VHandle
*)pFile
;
426 VFile
*pVFile
= p
->pVFile
;
428 if( pVFile
->nRef
==0 && pVFile
->zFilename
==0 ){
435 static int inmemRead(
436 sqlite3_file
*pFile
, /* Read from this open file */
437 void *pData
, /* Store content in this buffer */
438 int iAmt
, /* Bytes of content */
439 sqlite3_int64 iOfst
/* Start reading here */
441 VHandle
*pHandle
= (VHandle
*)pFile
;
442 VFile
*pVFile
= pHandle
->pVFile
;
443 if( iOfst
<0 || iOfst
>=pVFile
->sz
){
444 memset(pData
, 0, iAmt
);
445 return SQLITE_IOERR_SHORT_READ
;
447 if( iOfst
+iAmt
>pVFile
->sz
){
448 memset(pData
, 0, iAmt
);
449 iAmt
= (int)(pVFile
->sz
- iOfst
);
450 memcpy(pData
, pVFile
->a
, iAmt
);
451 return SQLITE_IOERR_SHORT_READ
;
453 memcpy(pData
, pVFile
->a
+ iOfst
, iAmt
);
456 static int inmemWrite(
457 sqlite3_file
*pFile
, /* Write to this file */
458 const void *pData
, /* Content to write */
459 int iAmt
, /* bytes to write */
460 sqlite3_int64 iOfst
/* Start writing here */
462 VHandle
*pHandle
= (VHandle
*)pFile
;
463 VFile
*pVFile
= pHandle
->pVFile
;
464 if( iOfst
+iAmt
> pVFile
->sz
){
465 if( iOfst
+iAmt
>= MX_FILE_SZ
){
468 pVFile
->a
= safe_realloc(pVFile
->a
, (int)(iOfst
+iAmt
));
469 if( iOfst
> pVFile
->sz
){
470 memset(pVFile
->a
+ pVFile
->sz
, 0, (int)(iOfst
- pVFile
->sz
));
472 pVFile
->sz
= (int)(iOfst
+ iAmt
);
474 memcpy(pVFile
->a
+ iOfst
, pData
, iAmt
);
477 static int inmemTruncate(sqlite3_file
*pFile
, sqlite3_int64 iSize
){
478 VHandle
*pHandle
= (VHandle
*)pFile
;
479 VFile
*pVFile
= pHandle
->pVFile
;
480 if( pVFile
->sz
>iSize
&& iSize
>=0 ) pVFile
->sz
= (int)iSize
;
483 static int inmemSync(sqlite3_file
*pFile
, int flags
){
486 static int inmemFileSize(sqlite3_file
*pFile
, sqlite3_int64
*pSize
){
487 *pSize
= ((VHandle
*)pFile
)->pVFile
->sz
;
490 static int inmemLock(sqlite3_file
*pFile
, int type
){
493 static int inmemUnlock(sqlite3_file
*pFile
, int type
){
496 static int inmemCheckReservedLock(sqlite3_file
*pFile
, int *pOut
){
500 static int inmemFileControl(sqlite3_file
*pFile
, int op
, void *pArg
){
501 return SQLITE_NOTFOUND
;
503 static int inmemSectorSize(sqlite3_file
*pFile
){
506 static int inmemDeviceCharacteristics(sqlite3_file
*pFile
){
508 SQLITE_IOCAP_SAFE_APPEND
|
509 SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
|
510 SQLITE_IOCAP_POWERSAFE_OVERWRITE
;
514 /* Method table for VHandle
516 static sqlite3_io_methods VHandleMethods
= {
518 /* xClose */ inmemClose
,
519 /* xRead */ inmemRead
,
520 /* xWrite */ inmemWrite
,
521 /* xTruncate */ inmemTruncate
,
522 /* xSync */ inmemSync
,
523 /* xFileSize */ inmemFileSize
,
524 /* xLock */ inmemLock
,
525 /* xUnlock */ inmemUnlock
,
526 /* xCheck... */ inmemCheckReservedLock
,
527 /* xFileCtrl */ inmemFileControl
,
528 /* xSectorSz */ inmemSectorSize
,
529 /* xDevchar */ inmemDeviceCharacteristics
,
539 ** Open a new file in the inmem VFS. All files are anonymous and are
542 static int inmemOpen(
544 const char *zFilename
,
549 VFile
*pVFile
= createVFile(zFilename
, 0, (unsigned char*)"");
550 VHandle
*pHandle
= (VHandle
*)pFile
;
554 pHandle
->pVFile
= pVFile
;
556 pFile
->pMethods
= &VHandleMethods
;
557 if( pOutFlags
) *pOutFlags
= openFlags
;
562 ** Delete a file by name
564 static int inmemDelete(
566 const char *zFilename
,
569 VFile
*pVFile
= findVFile(zFilename
);
570 if( pVFile
==0 ) return SQLITE_OK
;
571 if( pVFile
->nRef
==0 ){
572 free(pVFile
->zFilename
);
573 pVFile
->zFilename
= 0;
579 return SQLITE_IOERR_DELETE
;
582 /* Check for the existance of a file
584 static int inmemAccess(
586 const char *zFilename
,
590 VFile
*pVFile
= findVFile(zFilename
);
591 *pResOut
= pVFile
!=0;
595 /* Get the canonical pathname for a file
597 static int inmemFullPathname(
599 const char *zFilename
,
603 sqlite3_snprintf(nOut
, zOut
, "%s", zFilename
);
607 /* Always use the same random see, for repeatability.
609 static int inmemRandomness(sqlite3_vfs
*NotUsed
, int nBuf
, char *zBuf
){
610 memset(zBuf
, 0, nBuf
);
611 memcpy(zBuf
, &g
.uRandom
, nBuf
<sizeof(g
.uRandom
) ? nBuf
: sizeof(g
.uRandom
));
616 ** Register the VFS that reads from the g.aFile[] set of files.
618 static void inmemVfsRegister(int makeDefault
){
619 static sqlite3_vfs inmemVfs
;
620 sqlite3_vfs
*pDefault
= sqlite3_vfs_find(0);
621 inmemVfs
.iVersion
= 3;
622 inmemVfs
.szOsFile
= sizeof(VHandle
);
623 inmemVfs
.mxPathname
= 200;
624 inmemVfs
.zName
= "inmem";
625 inmemVfs
.xOpen
= inmemOpen
;
626 inmemVfs
.xDelete
= inmemDelete
;
627 inmemVfs
.xAccess
= inmemAccess
;
628 inmemVfs
.xFullPathname
= inmemFullPathname
;
629 inmemVfs
.xRandomness
= inmemRandomness
;
630 inmemVfs
.xSleep
= pDefault
->xSleep
;
631 inmemVfs
.xCurrentTimeInt64
= pDefault
->xCurrentTimeInt64
;
632 sqlite3_vfs_register(&inmemVfs
, makeDefault
);
636 ** Allowed values for the runFlags parameter to runSql()
638 #define SQL_TRACE 0x0001 /* Print each SQL statement as it is prepared */
639 #define SQL_OUTPUT 0x0002 /* Show the SQL output */
642 ** Run multiple commands of SQL. Similar to sqlite3_exec(), but does not
643 ** stop if an error is encountered.
645 static void runSql(sqlite3
*db
, const char *zSql
, unsigned runFlags
){
649 while( zSql
&& zSql
[0] ){
652 sqlite3_prepare_v2(db
, zSql
, -1, &pStmt
, &zMore
);
653 if( zMore
==zSql
) break;
654 if( runFlags
& SQL_TRACE
){
655 const char *z
= zSql
;
657 while( z
<zMore
&& ISSPACE(z
[0]) ) z
++;
658 n
= (int)(zMore
- z
);
659 while( n
>0 && ISSPACE(z
[n
-1]) ) n
--;
662 printf("TRACE: %.*s (error: %s)\n", n
, z
, sqlite3_errmsg(db
));
664 printf("TRACE: %.*s\n", n
, z
);
669 if( (runFlags
& SQL_OUTPUT
)==0 ){
670 while( SQLITE_ROW
==sqlite3_step(pStmt
) ){}
673 while( SQLITE_ROW
==sqlite3_step(pStmt
) ){
676 nCol
= sqlite3_column_count(pStmt
);
678 printf("--------------------------------------------\n");
680 for(i
=0; i
<nCol
; i
++){
681 int eType
= sqlite3_column_type(pStmt
,i
);
682 printf("%s = ", sqlite3_column_name(pStmt
,i
));
688 case SQLITE_INTEGER
: {
689 printf("INT %s\n", sqlite3_column_text(pStmt
,i
));
693 printf("FLOAT %s\n", sqlite3_column_text(pStmt
,i
));
697 printf("TEXT [%s]\n", sqlite3_column_text(pStmt
,i
));
701 printf("BLOB (%d bytes)\n", sqlite3_column_bytes(pStmt
,i
));
708 sqlite3_finalize(pStmt
);
714 ** Rebuild the database file.
716 ** (1) Remove duplicate entries
717 ** (2) Put all entries in order
720 static void rebuild_database(sqlite3
*db
){
722 rc
= sqlite3_exec(db
,
724 "CREATE TEMP TABLE dbx AS SELECT DISTINCT dbcontent FROM db;\n"
726 "INSERT INTO db(dbid, dbcontent) "
727 " SELECT NULL, dbcontent FROM dbx ORDER BY 2;\n"
729 "CREATE TEMP TABLE sx AS SELECT DISTINCT sqltext FROM xsql;\n"
730 "DELETE FROM xsql;\n"
731 "INSERT INTO xsql(sqlid,sqltext) "
732 " SELECT NULL, sqltext FROM sx ORDER BY 2;\n"
735 "PRAGMA page_size=1024;\n"
736 "VACUUM;\n", 0, 0, 0);
737 if( rc
) fatalError("cannot rebuild: %s", sqlite3_errmsg(db
));
741 ** Return the value of a hexadecimal digit. Return -1 if the input
742 ** is not a hex digit.
744 static int hexDigitValue(char c
){
745 if( c
>='0' && c
<='9' ) return c
- '0';
746 if( c
>='a' && c
<='f' ) return c
- 'a' + 10;
747 if( c
>='A' && c
<='F' ) return c
- 'A' + 10;
752 ** Interpret zArg as an integer value, possibly with suffixes.
754 static int integerValue(const char *zArg
){
756 static const struct { char *zSuffix
; int iMult
; } aMult
[] = {
758 { "MiB", 1024*1024 },
759 { "GiB", 1024*1024*1024 },
762 { "GB", 1000000000 },
772 }else if( zArg
[0]=='+' ){
775 if( zArg
[0]=='0' && zArg
[1]=='x' ){
778 while( (x
= hexDigitValue(zArg
[0]))>=0 ){
783 while( ISDIGIT(zArg
[0]) ){
784 v
= v
*10 + zArg
[0] - '0';
788 for(i
=0; i
<sizeof(aMult
)/sizeof(aMult
[0]); i
++){
789 if( sqlite3_stricmp(aMult
[i
].zSuffix
, zArg
)==0 ){
794 if( v
>0x7fffffff ) fatalError("parameter too large - max 2147483648");
795 return (int)(isNeg
? -v
: v
);
799 ** Print sketchy documentation for this utility program
801 static void showHelp(void){
802 printf("Usage: %s [options] SOURCE-DB ?ARGS...?\n", g
.zArgv0
);
804 "Read databases and SQL scripts from SOURCE-DB and execute each script against\n"
805 "each database, checking for crashes and memory leaks.\n"
807 " --cell-size-check Set the PRAGMA cell_size_check=ON\n"
808 " --dbid N Use only the database where dbid=N\n"
809 " --export-db DIR Write databases to files(s) in DIR. Works with --dbid\n"
810 " --export-sql DIR Write SQL to file(s) in DIR. Also works with --sqlid\n"
811 " --help Show this help text\n"
812 " --info Show information about SOURCE-DB w/o running tests\n"
813 " --limit-mem N Limit memory used by test SQLite instance to N bytes\n"
814 " --limit-vdbe Panic if any test runs for more than 100,000 cycles\n"
815 " --load-sql ARGS... Load SQL scripts fron files into SOURCE-DB\n"
816 " --load-db ARGS... Load template databases from files into SOURCE_DB\n"
817 " -m TEXT Add a description to the database\n"
818 " --native-vfs Use the native VFS for initially empty database files\n"
819 " --native-malloc Turn off MEMSYS3/5 and Lookaside\n"
820 " --oss-fuzz Enable OSS-FUZZ testing\n"
821 " --prng-seed N Seed value for the PRGN inside of SQLite\n"
822 " -q|--quiet Reduced output\n"
823 " --rebuild Rebuild and vacuum the database file\n"
824 " --result-trace Show the results of each SQL command\n"
825 " --sqlid N Use only SQL where sqlid=N\n"
826 " --timeout N Abort if any single test needs more than N seconds\n"
827 " -v|--verbose Increased output. Repeat for more output.\n"
831 int main(int argc
, char **argv
){
832 sqlite3_int64 iBegin
; /* Start time of this program */
833 int quietFlag
= 0; /* True if --quiet or -q */
834 int verboseFlag
= 0; /* True if --verbose or -v */
835 char *zInsSql
= 0; /* SQL statement for --load-db or --load-sql */
836 int iFirstInsArg
= 0; /* First argv[] for --load-db or --load-sql */
837 sqlite3
*db
= 0; /* The open database connection */
838 sqlite3_stmt
*pStmt
; /* A prepared statement */
839 int rc
; /* Result code from SQLite interface calls */
840 Blob
*pSql
; /* For looping over SQL scripts */
841 Blob
*pDb
; /* For looping over template databases */
842 int i
; /* Loop index for the argv[] loop */
843 int onlySqlid
= -1; /* --sqlid */
844 int onlyDbid
= -1; /* --dbid */
845 int nativeFlag
= 0; /* --native-vfs */
846 int rebuildFlag
= 0; /* --rebuild */
847 int vdbeLimitFlag
= 0; /* --limit-vdbe */
848 int infoFlag
= 0; /* --info */
849 int timeoutTest
= 0; /* undocumented --timeout-test flag */
850 int runFlags
= 0; /* Flags sent to runSql() */
851 char *zMsg
= 0; /* Add this message */
852 int nSrcDb
= 0; /* Number of source databases */
853 char **azSrcDb
= 0; /* Array of source database names */
854 int iSrcDb
; /* Loop over all source databases */
855 int nTest
= 0; /* Total number of tests performed */
856 char *zDbName
= ""; /* Appreviated name of a source database */
857 const char *zFailCode
= 0; /* Value of the TEST_FAILURE env variable */
858 int cellSzCkFlag
= 0; /* --cell-size-check */
859 int sqlFuzz
= 0; /* True for SQL fuzz. False for DB fuzz */
860 int iTimeout
= 120; /* Default 120-second timeout */
861 int nMem
= 0; /* Memory limit */
862 int nMemThisDb
= 0; /* Memory limit set by the CONFIG table */
863 char *zExpDb
= 0; /* Write Databases to files in this directory */
864 char *zExpSql
= 0; /* Write SQL to files in this directory */
865 void *pHeap
= 0; /* Heap for use by SQLite */
866 int ossFuzz
= 0; /* enable OSS-FUZZ testing */
867 int ossFuzzThisDb
= 0; /* ossFuzz value for this particular database */
868 int nativeMalloc
= 0; /* Turn off MEMSYS3/5 and lookaside if true */
869 sqlite3_vfs
*pDfltVfs
; /* The default VFS */
870 int openFlags4Data
; /* Flags for sqlite3_open_v2() */
872 sqlite3_initialize();
873 iBegin
= timeOfDay();
875 signal(SIGALRM
, timeoutHandler
);
878 openFlags4Data
= SQLITE_OPEN_READONLY
;
879 zFailCode
= getenv("TEST_FAILURE");
880 pDfltVfs
= sqlite3_vfs_find(0);
882 for(i
=1; i
<argc
; i
++){
883 const char *z
= argv
[i
];
887 if( strcmp(z
,"cell-size-check")==0 ){
890 if( strcmp(z
,"dbid")==0 ){
891 if( i
>=argc
-1 ) fatalError("missing arguments on %s", argv
[i
]);
892 onlyDbid
= integerValue(argv
[++i
]);
894 if( strcmp(z
,"export-db")==0 ){
895 if( i
>=argc
-1 ) fatalError("missing arguments on %s", argv
[i
]);
898 if( strcmp(z
,"export-sql")==0 ){
899 if( i
>=argc
-1 ) fatalError("missing arguments on %s", argv
[i
]);
902 if( strcmp(z
,"help")==0 ){
906 if( strcmp(z
,"info")==0 ){
909 if( strcmp(z
,"limit-mem")==0 ){
910 #if !defined(SQLITE_ENABLE_MEMSYS3) && !defined(SQLITE_ENABLE_MEMSYS5)
911 fatalError("the %s option requires -DSQLITE_ENABLE_MEMSYS5 or _MEMSYS3",
914 if( i
>=argc
-1 ) fatalError("missing arguments on %s", argv
[i
]);
915 nMem
= integerValue(argv
[++i
]);
918 if( strcmp(z
,"limit-vdbe")==0 ){
921 if( strcmp(z
,"load-sql")==0 ){
922 zInsSql
= "INSERT INTO xsql(sqltext)VALUES(CAST(readfile(?1) AS text))";
924 openFlags4Data
= SQLITE_OPEN_READWRITE
|SQLITE_OPEN_CREATE
;
927 if( strcmp(z
,"load-db")==0 ){
928 zInsSql
= "INSERT INTO db(dbcontent) VALUES(readfile(?1))";
930 openFlags4Data
= SQLITE_OPEN_READWRITE
|SQLITE_OPEN_CREATE
;
933 if( strcmp(z
,"m")==0 ){
934 if( i
>=argc
-1 ) fatalError("missing arguments on %s", argv
[i
]);
936 openFlags4Data
= SQLITE_OPEN_READWRITE
|SQLITE_OPEN_CREATE
;
938 if( strcmp(z
,"native-malloc")==0 ){
941 if( strcmp(z
,"native-vfs")==0 ){
944 if( strcmp(z
,"oss-fuzz")==0 ){
947 if( strcmp(z
,"prng-seed")==0 ){
948 if( i
>=argc
-1 ) fatalError("missing arguments on %s", argv
[i
]);
949 g
.uRandom
= atoi(argv
[++i
]);
951 if( strcmp(z
,"quiet")==0 || strcmp(z
,"q")==0 ){
955 if( strcmp(z
,"rebuild")==0 ){
957 openFlags4Data
= SQLITE_OPEN_READWRITE
;
959 if( strcmp(z
,"result-trace")==0 ){
960 runFlags
|= SQL_OUTPUT
;
962 if( strcmp(z
,"sqlid")==0 ){
963 if( i
>=argc
-1 ) fatalError("missing arguments on %s", argv
[i
]);
964 onlySqlid
= integerValue(argv
[++i
]);
966 if( strcmp(z
,"timeout")==0 ){
967 if( i
>=argc
-1 ) fatalError("missing arguments on %s", argv
[i
]);
968 iTimeout
= integerValue(argv
[++i
]);
970 if( strcmp(z
,"timeout-test")==0 ){
973 fatalError("timeout is not available on non-unix systems");
976 if( strcmp(z
,"verbose")==0 || strcmp(z
,"v")==0 ){
979 if( verboseFlag
>1 ) runFlags
|= SQL_TRACE
;
982 fatalError("unknown option: %s", argv
[i
]);
986 azSrcDb
= safe_realloc(azSrcDb
, nSrcDb
*sizeof(azSrcDb
[0]));
987 azSrcDb
[nSrcDb
-1] = argv
[i
];
990 if( nSrcDb
==0 ) fatalError("no source database specified");
993 fatalError("cannot change the description of more than one database");
996 fatalError("cannot import into more than one database");
1000 /* Process each source database separately */
1001 for(iSrcDb
=0; iSrcDb
<nSrcDb
; iSrcDb
++){
1002 rc
= sqlite3_open_v2(azSrcDb
[iSrcDb
], &db
,
1003 openFlags4Data
, pDfltVfs
->zName
);
1005 fatalError("cannot open source database %s - %s",
1006 azSrcDb
[iSrcDb
], sqlite3_errmsg(db
));
1009 /* Print the description, if there is one */
1012 zDbName
= azSrcDb
[iSrcDb
];
1013 i
= (int)strlen(zDbName
) - 1;
1014 while( i
>0 && zDbName
[i
-1]!='/' && zDbName
[i
-1]!='\\' ){ i
--; }
1016 sqlite3_prepare_v2(db
, "SELECT msg FROM readme", -1, &pStmt
, 0);
1017 if( pStmt
&& sqlite3_step(pStmt
)==SQLITE_ROW
){
1018 printf("%s: %s", zDbName
, sqlite3_column_text(pStmt
,0));
1020 printf("%s: (empty \"readme\")", zDbName
);
1022 sqlite3_finalize(pStmt
);
1023 sqlite3_prepare_v2(db
, "SELECT count(*) FROM db", -1, &pStmt
, 0);
1025 && sqlite3_step(pStmt
)==SQLITE_ROW
1026 && (n
= sqlite3_column_int(pStmt
,0))>0
1028 printf(" - %d DBs", n
);
1030 sqlite3_finalize(pStmt
);
1031 sqlite3_prepare_v2(db
, "SELECT count(*) FROM xsql", -1, &pStmt
, 0);
1033 && sqlite3_step(pStmt
)==SQLITE_ROW
1034 && (n
= sqlite3_column_int(pStmt
,0))>0
1036 printf(" - %d scripts", n
);
1038 sqlite3_finalize(pStmt
);
1044 rc
= sqlite3_exec(db
,
1045 "CREATE TABLE IF NOT EXISTS db(\n"
1046 " dbid INTEGER PRIMARY KEY, -- database id\n"
1047 " dbcontent BLOB -- database disk file image\n"
1049 "CREATE TABLE IF NOT EXISTS xsql(\n"
1050 " sqlid INTEGER PRIMARY KEY, -- SQL script id\n"
1051 " sqltext TEXT -- Text of SQL statements to run\n"
1053 "CREATE TABLE IF NOT EXISTS readme(\n"
1054 " msg TEXT -- Human-readable description of this file\n"
1056 if( rc
) fatalError("cannot create schema: %s", sqlite3_errmsg(db
));
1059 zSql
= sqlite3_mprintf(
1060 "DELETE FROM readme; INSERT INTO readme(msg) VALUES(%Q)", zMsg
);
1061 rc
= sqlite3_exec(db
, zSql
, 0, 0, 0);
1063 if( rc
) fatalError("cannot change description: %s", sqlite3_errmsg(db
));
1065 ossFuzzThisDb
= ossFuzz
;
1067 /* If the CONFIG(name,value) table exists, read db-specific settings
1068 ** from that table */
1069 if( sqlite3_table_column_metadata(db
,0,"config",0,0,0,0,0,0)==SQLITE_OK
){
1070 rc
= sqlite3_prepare_v2(db
, "SELECT name, value FROM config",
1072 if( rc
) fatalError("cannot prepare query of CONFIG table: %s",
1073 sqlite3_errmsg(db
));
1074 while( SQLITE_ROW
==sqlite3_step(pStmt
) ){
1075 const char *zName
= (const char *)sqlite3_column_text(pStmt
,0);
1076 if( zName
==0 ) continue;
1077 if( strcmp(zName
, "oss-fuzz")==0 ){
1078 ossFuzzThisDb
= sqlite3_column_int(pStmt
,1);
1079 if( verboseFlag
) printf("Config: oss-fuzz=%d\n", ossFuzzThisDb
);
1081 if( strcmp(zName
, "limit-mem")==0 && !nativeMalloc
){
1082 #if !defined(SQLITE_ENABLE_MEMSYS3) && !defined(SQLITE_ENABLE_MEMSYS5)
1083 fatalError("the limit-mem option requires -DSQLITE_ENABLE_MEMSYS5"
1086 nMemThisDb
= sqlite3_column_int(pStmt
,1);
1087 if( verboseFlag
) printf("Config: limit-mem=%d\n", nMemThisDb
);
1091 sqlite3_finalize(pStmt
);
1095 sqlite3_create_function(db
, "readfile", 1, SQLITE_UTF8
, 0,
1096 readfileFunc
, 0, 0);
1097 rc
= sqlite3_prepare_v2(db
, zInsSql
, -1, &pStmt
, 0);
1098 if( rc
) fatalError("cannot prepare statement [%s]: %s",
1099 zInsSql
, sqlite3_errmsg(db
));
1100 rc
= sqlite3_exec(db
, "BEGIN", 0, 0, 0);
1101 if( rc
) fatalError("cannot start a transaction");
1102 for(i
=iFirstInsArg
; i
<argc
; i
++){
1103 sqlite3_bind_text(pStmt
, 1, argv
[i
], -1, SQLITE_STATIC
);
1104 sqlite3_step(pStmt
);
1105 rc
= sqlite3_reset(pStmt
);
1106 if( rc
) fatalError("insert failed for %s", argv
[i
]);
1108 sqlite3_finalize(pStmt
);
1109 rc
= sqlite3_exec(db
, "COMMIT", 0, 0, 0);
1110 if( rc
) fatalError("cannot commit the transaction: %s",
1111 sqlite3_errmsg(db
));
1112 rebuild_database(db
);
1116 rc
= sqlite3_exec(db
, "PRAGMA query_only=1;", 0, 0, 0);
1117 if( rc
) fatalError("cannot set database to query-only");
1118 if( zExpDb
!=0 || zExpSql
!=0 ){
1119 sqlite3_create_function(db
, "writefile", 2, SQLITE_UTF8
, 0,
1120 writefileFunc
, 0, 0);
1123 "SELECT writefile(printf('%s/db%06d.db',?1,dbid),dbcontent),"
1124 " dbid, printf('%s/db%06d.db',?1,dbid), length(dbcontent)"
1125 " FROM db WHERE ?2<0 OR dbid=?2;";
1126 rc
= sqlite3_prepare_v2(db
, zExDb
, -1, &pStmt
, 0);
1127 if( rc
) fatalError("cannot prepare statement [%s]: %s",
1128 zExDb
, sqlite3_errmsg(db
));
1129 sqlite3_bind_text64(pStmt
, 1, zExpDb
, strlen(zExpDb
),
1130 SQLITE_STATIC
, SQLITE_UTF8
);
1131 sqlite3_bind_int(pStmt
, 2, onlyDbid
);
1132 while( sqlite3_step(pStmt
)==SQLITE_ROW
){
1133 printf("write db-%d (%d bytes) into %s\n",
1134 sqlite3_column_int(pStmt
,1),
1135 sqlite3_column_int(pStmt
,3),
1136 sqlite3_column_text(pStmt
,2));
1138 sqlite3_finalize(pStmt
);
1141 const char *zExSql
=
1142 "SELECT writefile(printf('%s/sql%06d.txt',?1,sqlid),sqltext),"
1143 " sqlid, printf('%s/sql%06d.txt',?1,sqlid), length(sqltext)"
1144 " FROM xsql WHERE ?2<0 OR sqlid=?2;";
1145 rc
= sqlite3_prepare_v2(db
, zExSql
, -1, &pStmt
, 0);
1146 if( rc
) fatalError("cannot prepare statement [%s]: %s",
1147 zExSql
, sqlite3_errmsg(db
));
1148 sqlite3_bind_text64(pStmt
, 1, zExpSql
, strlen(zExpSql
),
1149 SQLITE_STATIC
, SQLITE_UTF8
);
1150 sqlite3_bind_int(pStmt
, 2, onlySqlid
);
1151 while( sqlite3_step(pStmt
)==SQLITE_ROW
){
1152 printf("write sql-%d (%d bytes) into %s\n",
1153 sqlite3_column_int(pStmt
,1),
1154 sqlite3_column_int(pStmt
,3),
1155 sqlite3_column_text(pStmt
,2));
1157 sqlite3_finalize(pStmt
);
1163 /* Load all SQL script content and all initial database images from the
1166 blobListLoadFromDb(db
, "SELECT sqlid, sqltext FROM xsql", onlySqlid
,
1167 &g
.nSql
, &g
.pFirstSql
);
1168 if( g
.nSql
==0 ) fatalError("need at least one SQL script");
1169 blobListLoadFromDb(db
, "SELECT dbid, dbcontent FROM db", onlyDbid
,
1170 &g
.nDb
, &g
.pFirstDb
);
1172 g
.pFirstDb
= safe_realloc(0, sizeof(Blob
));
1173 memset(g
.pFirstDb
, 0, sizeof(Blob
));
1175 g
.pFirstDb
->seq
= 0;
1180 /* Print the description, if there is one */
1182 zDbName
= azSrcDb
[iSrcDb
];
1183 i
= (int)strlen(zDbName
) - 1;
1184 while( i
>0 && zDbName
[i
-1]!='/' && zDbName
[i
-1]!='\\' ){ i
--; }
1186 sqlite3_prepare_v2(db
, "SELECT msg FROM readme", -1, &pStmt
, 0);
1187 if( pStmt
&& sqlite3_step(pStmt
)==SQLITE_ROW
){
1188 printf("%s: %s\n", zDbName
, sqlite3_column_text(pStmt
,0));
1190 sqlite3_finalize(pStmt
);
1193 /* Rebuild the database, if requested */
1196 printf("%s: rebuilding... ", zDbName
);
1199 rebuild_database(db
);
1200 if( !quietFlag
) printf("done\n");
1203 /* Close the source database. Verify that no SQLite memory allocations are
1207 if( sqlite3_memory_used()>0 ){
1208 fatalError("SQLite has memory in use before the start of testing");
1211 /* Limit available memory, if requested */
1213 if( nMemThisDb
>0 && !nativeMalloc
){
1214 pHeap
= realloc(pHeap
, nMemThisDb
);
1216 fatalError("failed to allocate %d bytes of heap memory", nMem
);
1218 sqlite3_config(SQLITE_CONFIG_HEAP
, pHeap
, nMemThisDb
, 128);
1221 /* Disable lookaside with the --native-malloc option */
1223 sqlite3_config(SQLITE_CONFIG_LOOKASIDE
, 0, 0);
1226 /* Reset the in-memory virtual filesystem */
1229 /* Run a test using each SQL script against each database.
1231 if( !verboseFlag
&& !quietFlag
) printf("%s:", zDbName
);
1232 for(pSql
=g
.pFirstSql
; pSql
; pSql
=pSql
->pNext
){
1233 for(pDb
=g
.pFirstDb
; pDb
; pDb
=pDb
->pNext
){
1235 const char *zVfs
= "inmem";
1236 sqlite3_snprintf(sizeof(g
.zTestName
), g
.zTestName
, "sqlid=%d,dbid=%d",
1239 printf("%s\n", g
.zTestName
);
1241 }else if( !quietFlag
){
1242 static int prevAmt
= -1;
1243 int idx
= pSql
->seq
*g
.nDb
+ pDb
->id
- 1;
1244 int amt
= idx
*10/(g
.nDb
*g
.nSql
);
1246 printf(" %d%%", amt
*10);
1251 createVFile("main.db", pDb
->sz
, pDb
->a
);
1252 sqlite3_randomness(0,0);
1253 if( ossFuzzThisDb
){
1254 #ifndef SQLITE_OSS_FUZZ
1255 fatalError("--oss-fuzz not supported: recompile"
1256 " with -DSQLITE_OSS_FUZZ");
1258 extern int LLVMFuzzerTestOneInput(const uint8_t*, size_t);
1259 LLVMFuzzerTestOneInput((const uint8_t*)pSql
->a
, (size_t)pSql
->sz
);
1262 openFlags
= SQLITE_OPEN_CREATE
| SQLITE_OPEN_READWRITE
;
1263 if( nativeFlag
&& pDb
->sz
==0 ){
1264 openFlags
|= SQLITE_OPEN_MEMORY
;
1267 rc
= sqlite3_open_v2("main.db", &db
, openFlags
, zVfs
);
1268 if( rc
) fatalError("cannot open inmem database");
1269 sqlite3_limit(db
, SQLITE_LIMIT_LENGTH
, 100000000);
1270 sqlite3_limit(db
, SQLITE_LIMIT_LIKE_PATTERN_LENGTH
, 50);
1271 if( cellSzCkFlag
) runSql(db
, "PRAGMA cell_size_check=ON", runFlags
);
1273 #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
1274 if( sqlFuzz
|| vdbeLimitFlag
){
1275 sqlite3_progress_handler(db
, 100000, progressHandler
,
1280 runSql(db
, (char*)pSql
->a
, runFlags
);
1281 }while( timeoutTest
);
1283 sqlite3_exec(db
, "PRAGMA temp_store_directory=''", 0, 0, 0);
1286 if( sqlite3_memory_used()>0 ){
1287 fatalError("memory leak: %lld bytes outstanding",
1288 sqlite3_memory_used());
1294 /* Simulate an error if the TEST_FAILURE environment variable is "5".
1295 ** This is used to verify that automated test script really do spot
1296 ** errors that occur in this test program.
1299 if( zFailCode
[0]=='5' && zFailCode
[1]==0 ){
1300 fatalError("simulated failure");
1301 }else if( zFailCode
[0]!=0 ){
1302 /* If TEST_FAILURE is something other than 5, just exit the test
1304 printf("\nExit early due to TEST_FAILURE being set\n");
1306 goto sourcedb_cleanup
;
1311 if( !quietFlag
&& !verboseFlag
){
1312 printf(" 100%% - %d tests\n", g
.nDb
*g
.nSql
);
1315 /* Clean up at the end of processing a single source database
1318 blobListFree(g
.pFirstSql
);
1319 blobListFree(g
.pFirstDb
);
1322 } /* End loop over all source databases */
1325 sqlite3_int64 iElapse
= timeOfDay() - iBegin
;
1326 printf("fuzzcheck: 0 errors out of %d tests in %d.%03d seconds\n"
1328 nTest
, (int)(iElapse
/1000), (int)(iElapse
%1000),
1329 sqlite3_libversion(), sqlite3_sourceid());