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
88 ** Files in the virtual file system.
90 typedef struct VFile VFile
;
92 char *zFilename
; /* Filename. NULL for delete-on-close. From malloc() */
93 int sz
; /* Size of the file in bytes */
94 int nRef
; /* Number of references to this file */
95 unsigned char *a
; /* Content of the file. From malloc() */
97 typedef struct VHandle VHandle
;
99 sqlite3_file base
; /* Base class. Must be first */
100 VFile
*pVFile
; /* The underlying file */
104 ** The value of a database file template, or of an SQL script
106 typedef struct Blob Blob
;
108 Blob
*pNext
; /* Next in a list */
109 int id
; /* Id of this Blob */
110 int seq
; /* Sequence number */
111 int sz
; /* Size of this Blob in bytes */
112 unsigned char a
[1]; /* Blob content. Extra space allocated as needed. */
116 ** Maximum number of files in the in-memory virtual filesystem.
121 ** Maximum allowed file size
123 #define MX_FILE_SZ 10000000
126 ** All global variables are gathered into the "g" singleton.
128 static struct GlobalVars
{
129 const char *zArgv0
; /* Name of program */
130 VFile aFile
[MX_FILE
]; /* The virtual filesystem */
131 int nDb
; /* Number of template databases */
132 Blob
*pFirstDb
; /* Content of first template database */
133 int nSql
; /* Number of SQL scripts */
134 Blob
*pFirstSql
; /* First SQL script */
135 unsigned int uRandom
; /* Seed for the SQLite PRNG */
136 char zTestName
[100]; /* Name of current test */
140 ** Print an error message and quit.
142 static void fatalError(const char *zFormat
, ...){
144 if( g
.zTestName
[0] ){
145 fprintf(stderr
, "%s (%s): ", g
.zArgv0
, g
.zTestName
);
147 fprintf(stderr
, "%s: ", g
.zArgv0
);
149 va_start(ap
, zFormat
);
150 vfprintf(stderr
, zFormat
, ap
);
152 fprintf(stderr
, "\n");
160 static void timeoutHandler(int NotUsed
){
162 fatalError("timeout\n");
167 ** Set the an alarm to go off after N seconds. Disable the alarm
170 static void setAlarm(int N
){
178 #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
180 ** This an SQL progress handler. After an SQL statement has run for
181 ** many steps, we want to interrupt it. This guards against infinite
182 ** loops from recursive common table expressions.
184 ** *pVdbeLimitFlag is true if the --limit-vdbe command-line option is used.
185 ** In that case, hitting the progress handler is a fatal error.
187 static int progressHandler(void *pVdbeLimitFlag
){
188 if( *(int*)pVdbeLimitFlag
) fatalError("too many VDBE cycles");
194 ** Reallocate memory. Show and error and quit if unable.
196 static void *safe_realloc(void *pOld
, int szNew
){
197 void *pNew
= realloc(pOld
, szNew
<=0 ? 1 : szNew
);
198 if( pNew
==0 ) fatalError("unable to realloc for %d bytes", szNew
);
203 ** Initialize the virtual file system.
205 static void formatVfs(void){
207 for(i
=0; i
<MX_FILE
; i
++){
209 g
.aFile
[i
].zFilename
= 0;
217 ** Erase all information in the virtual file system.
219 static void reformatVfs(void){
221 for(i
=0; i
<MX_FILE
; i
++){
222 if( g
.aFile
[i
].sz
<0 ) continue;
223 if( g
.aFile
[i
].zFilename
){
224 free(g
.aFile
[i
].zFilename
);
225 g
.aFile
[i
].zFilename
= 0;
227 if( g
.aFile
[i
].nRef
>0 ){
228 fatalError("file %d still open. nRef=%d", i
, g
.aFile
[i
].nRef
);
238 ** Find a VFile by name
240 static VFile
*findVFile(const char *zName
){
242 if( zName
==0 ) return 0;
243 for(i
=0; i
<MX_FILE
; i
++){
244 if( g
.aFile
[i
].zFilename
==0 ) continue;
245 if( strcmp(g
.aFile
[i
].zFilename
, zName
)==0 ) return &g
.aFile
[i
];
251 ** Find a VFile by name. Create it if it does not already exist and
252 ** initialize it to the size and content given.
254 ** Return NULL only if the filesystem is full.
256 static VFile
*createVFile(const char *zName
, int sz
, unsigned char *pData
){
257 VFile
*pNew
= findVFile(zName
);
259 if( pNew
) return pNew
;
260 for(i
=0; i
<MX_FILE
&& g
.aFile
[i
].sz
>=0; i
++){}
261 if( i
>=MX_FILE
) return 0;
264 int nName
= (int)strlen(zName
)+1;
265 pNew
->zFilename
= safe_realloc(0, nName
);
266 memcpy(pNew
->zFilename
, zName
, nName
);
272 pNew
->a
= safe_realloc(0, sz
);
273 if( sz
>0 ) memcpy(pNew
->a
, pData
, sz
);
279 ** Implementation of the "readfile(X)" SQL function. The entire content
280 ** of the file named X is read and returned as a BLOB. NULL is returned
281 ** if the file does not exist or is unreadable.
283 static void readfileFunc(
284 sqlite3_context
*context
,
293 zName
= (const char*)sqlite3_value_text(argv
[0]);
294 if( zName
==0 ) return;
295 in
= fopen(zName
, "rb");
297 fseek(in
, 0, SEEK_END
);
300 pBuf
= sqlite3_malloc64( nIn
);
301 if( pBuf
&& 1==fread(pBuf
, nIn
, 1, in
) ){
302 sqlite3_result_blob(context
, pBuf
, nIn
, sqlite3_free
);
310 ** Implementation of the "writefile(X,Y)" SQL function. The argument Y
311 ** is written into file X. The number of bytes written is returned. Or
312 ** NULL is returned if something goes wrong, such as being unable to open
313 ** file X for writing.
315 static void writefileFunc(
316 sqlite3_context
*context
,
326 zFile
= (const char*)sqlite3_value_text(argv
[0]);
327 if( zFile
==0 ) return;
328 out
= fopen(zFile
, "wb");
330 z
= (const char*)sqlite3_value_blob(argv
[1]);
334 rc
= fwrite(z
, 1, sqlite3_value_bytes(argv
[1]), out
);
337 sqlite3_result_int64(context
, rc
);
342 ** Load a list of Blob objects from the database
344 static void blobListLoadFromDb(
345 sqlite3
*db
, /* Read from this database */
346 const char *zSql
, /* Query used to extract the blobs */
347 int onlyId
, /* Only load where id is this value */
348 int *pN
, /* OUT: Write number of blobs loaded here */
349 Blob
**ppList
/* OUT: Write the head of the blob list here */
359 z2
= sqlite3_mprintf("%s WHERE rowid=%d", zSql
, onlyId
);
361 z2
= sqlite3_mprintf("%s", zSql
);
363 rc
= sqlite3_prepare_v2(db
, z2
, -1, &pStmt
, 0);
365 if( rc
) fatalError("%s", sqlite3_errmsg(db
));
368 while( SQLITE_ROW
==sqlite3_step(pStmt
) ){
369 int sz
= sqlite3_column_bytes(pStmt
, 1);
370 Blob
*pNew
= safe_realloc(0, sizeof(*pNew
)+sz
);
371 pNew
->id
= sqlite3_column_int(pStmt
, 0);
375 memcpy(pNew
->a
, sqlite3_column_blob(pStmt
,1), sz
);
380 sqlite3_finalize(pStmt
);
382 *ppList
= head
.pNext
;
386 ** Free a list of Blob objects
388 static void blobListFree(Blob
*p
){
398 /* Return the current wall-clock time */
399 static sqlite3_int64
timeOfDay(void){
400 static sqlite3_vfs
*clockVfs
= 0;
402 if( clockVfs
==0 ) clockVfs
= sqlite3_vfs_find(0);
403 if( clockVfs
->iVersion
>=1 && clockVfs
->xCurrentTimeInt64
!=0 ){
404 clockVfs
->xCurrentTimeInt64(clockVfs
, &t
);
407 clockVfs
->xCurrentTime(clockVfs
, &r
);
408 t
= (sqlite3_int64
)(r
*86400000.0);
413 /* Methods for the VHandle object
415 static int inmemClose(sqlite3_file
*pFile
){
416 VHandle
*p
= (VHandle
*)pFile
;
417 VFile
*pVFile
= p
->pVFile
;
419 if( pVFile
->nRef
==0 && pVFile
->zFilename
==0 ){
426 static int inmemRead(
427 sqlite3_file
*pFile
, /* Read from this open file */
428 void *pData
, /* Store content in this buffer */
429 int iAmt
, /* Bytes of content */
430 sqlite3_int64 iOfst
/* Start reading here */
432 VHandle
*pHandle
= (VHandle
*)pFile
;
433 VFile
*pVFile
= pHandle
->pVFile
;
434 if( iOfst
<0 || iOfst
>=pVFile
->sz
){
435 memset(pData
, 0, iAmt
);
436 return SQLITE_IOERR_SHORT_READ
;
438 if( iOfst
+iAmt
>pVFile
->sz
){
439 memset(pData
, 0, iAmt
);
440 iAmt
= (int)(pVFile
->sz
- iOfst
);
441 memcpy(pData
, pVFile
->a
, iAmt
);
442 return SQLITE_IOERR_SHORT_READ
;
444 memcpy(pData
, pVFile
->a
+ iOfst
, iAmt
);
447 static int inmemWrite(
448 sqlite3_file
*pFile
, /* Write to this file */
449 const void *pData
, /* Content to write */
450 int iAmt
, /* bytes to write */
451 sqlite3_int64 iOfst
/* Start writing here */
453 VHandle
*pHandle
= (VHandle
*)pFile
;
454 VFile
*pVFile
= pHandle
->pVFile
;
455 if( iOfst
+iAmt
> pVFile
->sz
){
456 if( iOfst
+iAmt
>= MX_FILE_SZ
){
459 pVFile
->a
= safe_realloc(pVFile
->a
, (int)(iOfst
+iAmt
));
460 if( iOfst
> pVFile
->sz
){
461 memset(pVFile
->a
+ pVFile
->sz
, 0, (int)(iOfst
- pVFile
->sz
));
463 pVFile
->sz
= (int)(iOfst
+ iAmt
);
465 memcpy(pVFile
->a
+ iOfst
, pData
, iAmt
);
468 static int inmemTruncate(sqlite3_file
*pFile
, sqlite3_int64 iSize
){
469 VHandle
*pHandle
= (VHandle
*)pFile
;
470 VFile
*pVFile
= pHandle
->pVFile
;
471 if( pVFile
->sz
>iSize
&& iSize
>=0 ) pVFile
->sz
= (int)iSize
;
474 static int inmemSync(sqlite3_file
*pFile
, int flags
){
477 static int inmemFileSize(sqlite3_file
*pFile
, sqlite3_int64
*pSize
){
478 *pSize
= ((VHandle
*)pFile
)->pVFile
->sz
;
481 static int inmemLock(sqlite3_file
*pFile
, int type
){
484 static int inmemUnlock(sqlite3_file
*pFile
, int type
){
487 static int inmemCheckReservedLock(sqlite3_file
*pFile
, int *pOut
){
491 static int inmemFileControl(sqlite3_file
*pFile
, int op
, void *pArg
){
492 return SQLITE_NOTFOUND
;
494 static int inmemSectorSize(sqlite3_file
*pFile
){
497 static int inmemDeviceCharacteristics(sqlite3_file
*pFile
){
499 SQLITE_IOCAP_SAFE_APPEND
|
500 SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
|
501 SQLITE_IOCAP_POWERSAFE_OVERWRITE
;
505 /* Method table for VHandle
507 static sqlite3_io_methods VHandleMethods
= {
509 /* xClose */ inmemClose
,
510 /* xRead */ inmemRead
,
511 /* xWrite */ inmemWrite
,
512 /* xTruncate */ inmemTruncate
,
513 /* xSync */ inmemSync
,
514 /* xFileSize */ inmemFileSize
,
515 /* xLock */ inmemLock
,
516 /* xUnlock */ inmemUnlock
,
517 /* xCheck... */ inmemCheckReservedLock
,
518 /* xFileCtrl */ inmemFileControl
,
519 /* xSectorSz */ inmemSectorSize
,
520 /* xDevchar */ inmemDeviceCharacteristics
,
530 ** Open a new file in the inmem VFS. All files are anonymous and are
533 static int inmemOpen(
535 const char *zFilename
,
540 VFile
*pVFile
= createVFile(zFilename
, 0, (unsigned char*)"");
541 VHandle
*pHandle
= (VHandle
*)pFile
;
545 pHandle
->pVFile
= pVFile
;
547 pFile
->pMethods
= &VHandleMethods
;
548 if( pOutFlags
) *pOutFlags
= openFlags
;
553 ** Delete a file by name
555 static int inmemDelete(
557 const char *zFilename
,
560 VFile
*pVFile
= findVFile(zFilename
);
561 if( pVFile
==0 ) return SQLITE_OK
;
562 if( pVFile
->nRef
==0 ){
563 free(pVFile
->zFilename
);
564 pVFile
->zFilename
= 0;
570 return SQLITE_IOERR_DELETE
;
573 /* Check for the existance of a file
575 static int inmemAccess(
577 const char *zFilename
,
581 VFile
*pVFile
= findVFile(zFilename
);
582 *pResOut
= pVFile
!=0;
586 /* Get the canonical pathname for a file
588 static int inmemFullPathname(
590 const char *zFilename
,
594 sqlite3_snprintf(nOut
, zOut
, "%s", zFilename
);
598 /* Always use the same random see, for repeatability.
600 static int inmemRandomness(sqlite3_vfs
*NotUsed
, int nBuf
, char *zBuf
){
601 memset(zBuf
, 0, nBuf
);
602 memcpy(zBuf
, &g
.uRandom
, nBuf
<sizeof(g
.uRandom
) ? nBuf
: sizeof(g
.uRandom
));
607 ** Register the VFS that reads from the g.aFile[] set of files.
609 static void inmemVfsRegister(int makeDefault
){
610 static sqlite3_vfs inmemVfs
;
611 sqlite3_vfs
*pDefault
= sqlite3_vfs_find(0);
612 inmemVfs
.iVersion
= 3;
613 inmemVfs
.szOsFile
= sizeof(VHandle
);
614 inmemVfs
.mxPathname
= 200;
615 inmemVfs
.zName
= "inmem";
616 inmemVfs
.xOpen
= inmemOpen
;
617 inmemVfs
.xDelete
= inmemDelete
;
618 inmemVfs
.xAccess
= inmemAccess
;
619 inmemVfs
.xFullPathname
= inmemFullPathname
;
620 inmemVfs
.xRandomness
= inmemRandomness
;
621 inmemVfs
.xSleep
= pDefault
->xSleep
;
622 inmemVfs
.xCurrentTimeInt64
= pDefault
->xCurrentTimeInt64
;
623 sqlite3_vfs_register(&inmemVfs
, makeDefault
);
627 ** Allowed values for the runFlags parameter to runSql()
629 #define SQL_TRACE 0x0001 /* Print each SQL statement as it is prepared */
630 #define SQL_OUTPUT 0x0002 /* Show the SQL output */
633 ** Run multiple commands of SQL. Similar to sqlite3_exec(), but does not
634 ** stop if an error is encountered.
636 static void runSql(sqlite3
*db
, const char *zSql
, unsigned runFlags
){
640 while( zSql
&& zSql
[0] ){
643 sqlite3_prepare_v2(db
, zSql
, -1, &pStmt
, &zMore
);
644 if( zMore
==zSql
) break;
645 if( runFlags
& SQL_TRACE
){
646 const char *z
= zSql
;
648 while( z
<zMore
&& ISSPACE(z
[0]) ) z
++;
649 n
= (int)(zMore
- z
);
650 while( n
>0 && ISSPACE(z
[n
-1]) ) n
--;
653 printf("TRACE: %.*s (error: %s)\n", n
, z
, sqlite3_errmsg(db
));
655 printf("TRACE: %.*s\n", n
, z
);
660 if( (runFlags
& SQL_OUTPUT
)==0 ){
661 while( SQLITE_ROW
==sqlite3_step(pStmt
) ){}
664 while( SQLITE_ROW
==sqlite3_step(pStmt
) ){
667 nCol
= sqlite3_column_count(pStmt
);
669 printf("--------------------------------------------\n");
671 for(i
=0; i
<nCol
; i
++){
672 int eType
= sqlite3_column_type(pStmt
,i
);
673 printf("%s = ", sqlite3_column_name(pStmt
,i
));
679 case SQLITE_INTEGER
: {
680 printf("INT %s\n", sqlite3_column_text(pStmt
,i
));
684 printf("FLOAT %s\n", sqlite3_column_text(pStmt
,i
));
688 printf("TEXT [%s]\n", sqlite3_column_text(pStmt
,i
));
692 printf("BLOB (%d bytes)\n", sqlite3_column_bytes(pStmt
,i
));
699 sqlite3_finalize(pStmt
);
705 ** Rebuild the database file.
707 ** (1) Remove duplicate entries
708 ** (2) Put all entries in order
711 static void rebuild_database(sqlite3
*db
){
713 rc
= sqlite3_exec(db
,
715 "CREATE TEMP TABLE dbx AS SELECT DISTINCT dbcontent FROM db;\n"
717 "INSERT INTO db(dbid, dbcontent) SELECT NULL, dbcontent FROM dbx ORDER BY 2;\n"
719 "CREATE TEMP TABLE sx AS SELECT DISTINCT sqltext FROM xsql;\n"
720 "DELETE FROM xsql;\n"
721 "INSERT INTO xsql(sqlid,sqltext) SELECT NULL, sqltext FROM sx ORDER BY 2;\n"
724 "PRAGMA page_size=1024;\n"
725 "VACUUM;\n", 0, 0, 0);
726 if( rc
) fatalError("cannot rebuild: %s", sqlite3_errmsg(db
));
730 ** Return the value of a hexadecimal digit. Return -1 if the input
731 ** is not a hex digit.
733 static int hexDigitValue(char c
){
734 if( c
>='0' && c
<='9' ) return c
- '0';
735 if( c
>='a' && c
<='f' ) return c
- 'a' + 10;
736 if( c
>='A' && c
<='F' ) return c
- 'A' + 10;
741 ** Interpret zArg as an integer value, possibly with suffixes.
743 static int integerValue(const char *zArg
){
745 static const struct { char *zSuffix
; int iMult
; } aMult
[] = {
747 { "MiB", 1024*1024 },
748 { "GiB", 1024*1024*1024 },
751 { "GB", 1000000000 },
761 }else if( zArg
[0]=='+' ){
764 if( zArg
[0]=='0' && zArg
[1]=='x' ){
767 while( (x
= hexDigitValue(zArg
[0]))>=0 ){
772 while( ISDIGIT(zArg
[0]) ){
773 v
= v
*10 + zArg
[0] - '0';
777 for(i
=0; i
<sizeof(aMult
)/sizeof(aMult
[0]); i
++){
778 if( sqlite3_stricmp(aMult
[i
].zSuffix
, zArg
)==0 ){
783 if( v
>0x7fffffff ) fatalError("parameter too large - max 2147483648");
784 return (int)(isNeg
? -v
: v
);
788 ** Print sketchy documentation for this utility program
790 static void showHelp(void){
791 printf("Usage: %s [options] SOURCE-DB ?ARGS...?\n", g
.zArgv0
);
793 "Read databases and SQL scripts from SOURCE-DB and execute each script against\n"
794 "each database, checking for crashes and memory leaks.\n"
796 " --cell-size-check Set the PRAGMA cell_size_check=ON\n"
797 " --dbid N Use only the database where dbid=N\n"
798 " --export-db DIR Write databases to files(s) in DIR. Works with --dbid\n"
799 " --export-sql DIR Write SQL to file(s) in DIR. Also works with --sqlid\n"
800 " --help Show this help text\n"
801 " -q|--quiet Reduced output\n"
802 " --limit-mem N Limit memory used by test SQLite instance to N bytes\n"
803 " --limit-vdbe Panic if any test runs for more than 100,000 cycles\n"
804 " --load-sql ARGS... Load SQL scripts fro files into SOURCE-DB\n"
805 " --load-db ARGS... Load template databases from files into SOURCE_DB\n"
806 " -m TEXT Add a description to the database\n"
807 " --native-vfs Use the native VFS for initially empty database files\n"
808 " --native-malloc Turn off MEMSYS3/5 and Lookaside\n"
809 " --oss-fuzz Enable OSS-FUZZ testing\n"
810 " --prng-seed N Seed value for the PRGN inside of SQLite\n"
811 " --rebuild Rebuild and vacuum the database file\n"
812 " --result-trace Show the results of each SQL command\n"
813 " --sqlid N Use only SQL where sqlid=N\n"
814 " --timeout N Abort if any single test needs more than N seconds\n"
815 " -v|--verbose Increased output. Repeat for more output.\n"
819 int main(int argc
, char **argv
){
820 sqlite3_int64 iBegin
; /* Start time of this program */
821 int quietFlag
= 0; /* True if --quiet or -q */
822 int verboseFlag
= 0; /* True if --verbose or -v */
823 char *zInsSql
= 0; /* SQL statement for --load-db or --load-sql */
824 int iFirstInsArg
= 0; /* First argv[] to use for --load-db or --load-sql */
825 sqlite3
*db
= 0; /* The open database connection */
826 sqlite3_stmt
*pStmt
; /* A prepared statement */
827 int rc
; /* Result code from SQLite interface calls */
828 Blob
*pSql
; /* For looping over SQL scripts */
829 Blob
*pDb
; /* For looping over template databases */
830 int i
; /* Loop index for the argv[] loop */
831 int onlySqlid
= -1; /* --sqlid */
832 int onlyDbid
= -1; /* --dbid */
833 int nativeFlag
= 0; /* --native-vfs */
834 int rebuildFlag
= 0; /* --rebuild */
835 int vdbeLimitFlag
= 0; /* --limit-vdbe */
836 int timeoutTest
= 0; /* undocumented --timeout-test flag */
837 int runFlags
= 0; /* Flags sent to runSql() */
838 char *zMsg
= 0; /* Add this message */
839 int nSrcDb
= 0; /* Number of source databases */
840 char **azSrcDb
= 0; /* Array of source database names */
841 int iSrcDb
; /* Loop over all source databases */
842 int nTest
= 0; /* Total number of tests performed */
843 char *zDbName
= ""; /* Appreviated name of a source database */
844 const char *zFailCode
= 0; /* Value of the TEST_FAILURE environment variable */
845 int cellSzCkFlag
= 0; /* --cell-size-check */
846 int sqlFuzz
= 0; /* True for SQL fuzz testing. False for DB fuzz */
847 int iTimeout
= 120; /* Default 120-second timeout */
848 int nMem
= 0; /* Memory limit */
849 int nMemThisDb
= 0; /* Memory limit set by the CONFIG table */
850 char *zExpDb
= 0; /* Write Databases to files in this directory */
851 char *zExpSql
= 0; /* Write SQL to files in this directory */
852 void *pHeap
= 0; /* Heap for use by SQLite */
853 int ossFuzz
= 0; /* enable OSS-FUZZ testing */
854 int ossFuzzThisDb
= 0; /* ossFuzz value for this particular database */
855 int nativeMalloc
= 0; /* Turn off MEMSYS3/5 and lookaside if true */
856 sqlite3_vfs
*pDfltVfs
; /* The default VFS */
858 iBegin
= timeOfDay();
860 signal(SIGALRM
, timeoutHandler
);
863 zFailCode
= getenv("TEST_FAILURE");
864 pDfltVfs
= sqlite3_vfs_find(0);
866 for(i
=1; i
<argc
; i
++){
867 const char *z
= argv
[i
];
871 if( strcmp(z
,"cell-size-check")==0 ){
874 if( strcmp(z
,"dbid")==0 ){
875 if( i
>=argc
-1 ) fatalError("missing arguments on %s", argv
[i
]);
876 onlyDbid
= integerValue(argv
[++i
]);
878 if( strcmp(z
,"export-db")==0 ){
879 if( i
>=argc
-1 ) fatalError("missing arguments on %s", argv
[i
]);
882 if( strcmp(z
,"export-sql")==0 ){
883 if( i
>=argc
-1 ) fatalError("missing arguments on %s", argv
[i
]);
886 if( strcmp(z
,"help")==0 ){
890 if( strcmp(z
,"limit-mem")==0 ){
891 #if !defined(SQLITE_ENABLE_MEMSYS3) && !defined(SQLITE_ENABLE_MEMSYS5)
892 fatalError("the %s option requires -DSQLITE_ENABLE_MEMSYS5 or _MEMSYS3",
895 if( i
>=argc
-1 ) fatalError("missing arguments on %s", argv
[i
]);
896 nMem
= integerValue(argv
[++i
]);
899 if( strcmp(z
,"limit-vdbe")==0 ){
902 if( strcmp(z
,"load-sql")==0 ){
903 zInsSql
= "INSERT INTO xsql(sqltext) VALUES(CAST(readfile(?1) AS text))";
907 if( strcmp(z
,"load-db")==0 ){
908 zInsSql
= "INSERT INTO db(dbcontent) VALUES(readfile(?1))";
912 if( strcmp(z
,"m")==0 ){
913 if( i
>=argc
-1 ) fatalError("missing arguments on %s", argv
[i
]);
916 if( strcmp(z
,"native-malloc")==0 ){
919 if( strcmp(z
,"native-vfs")==0 ){
922 if( strcmp(z
,"oss-fuzz")==0 ){
925 if( strcmp(z
,"prng-seed")==0 ){
926 if( i
>=argc
-1 ) fatalError("missing arguments on %s", argv
[i
]);
927 g
.uRandom
= atoi(argv
[++i
]);
929 if( strcmp(z
,"quiet")==0 || strcmp(z
,"q")==0 ){
933 if( strcmp(z
,"rebuild")==0 ){
936 if( strcmp(z
,"result-trace")==0 ){
937 runFlags
|= SQL_OUTPUT
;
939 if( strcmp(z
,"sqlid")==0 ){
940 if( i
>=argc
-1 ) fatalError("missing arguments on %s", argv
[i
]);
941 onlySqlid
= integerValue(argv
[++i
]);
943 if( strcmp(z
,"timeout")==0 ){
944 if( i
>=argc
-1 ) fatalError("missing arguments on %s", argv
[i
]);
945 iTimeout
= integerValue(argv
[++i
]);
947 if( strcmp(z
,"timeout-test")==0 ){
950 fatalError("timeout is not available on non-unix systems");
953 if( strcmp(z
,"verbose")==0 || strcmp(z
,"v")==0 ){
956 if( verboseFlag
>1 ) runFlags
|= SQL_TRACE
;
959 fatalError("unknown option: %s", argv
[i
]);
963 azSrcDb
= safe_realloc(azSrcDb
, nSrcDb
*sizeof(azSrcDb
[0]));
964 azSrcDb
[nSrcDb
-1] = argv
[i
];
967 if( nSrcDb
==0 ) fatalError("no source database specified");
970 fatalError("cannot change the description of more than one database");
973 fatalError("cannot import into more than one database");
977 /* Process each source database separately */
978 for(iSrcDb
=0; iSrcDb
<nSrcDb
; iSrcDb
++){
979 rc
= sqlite3_open_v2(azSrcDb
[iSrcDb
], &db
,
980 SQLITE_OPEN_READWRITE
, pDfltVfs
->zName
);
982 fatalError("cannot open source database %s - %s",
983 azSrcDb
[iSrcDb
], sqlite3_errmsg(db
));
985 rc
= sqlite3_exec(db
,
986 "CREATE TABLE IF NOT EXISTS db(\n"
987 " dbid INTEGER PRIMARY KEY, -- database id\n"
988 " dbcontent BLOB -- database disk file image\n"
990 "CREATE TABLE IF NOT EXISTS xsql(\n"
991 " sqlid INTEGER PRIMARY KEY, -- SQL script id\n"
992 " sqltext TEXT -- Text of SQL statements to run\n"
994 "CREATE TABLE IF NOT EXISTS readme(\n"
995 " msg TEXT -- Human-readable description of this file\n"
997 if( rc
) fatalError("cannot create schema: %s", sqlite3_errmsg(db
));
1000 zSql
= sqlite3_mprintf(
1001 "DELETE FROM readme; INSERT INTO readme(msg) VALUES(%Q)", zMsg
);
1002 rc
= sqlite3_exec(db
, zSql
, 0, 0, 0);
1004 if( rc
) fatalError("cannot change description: %s", sqlite3_errmsg(db
));
1006 ossFuzzThisDb
= ossFuzz
;
1008 /* If the CONFIG(name,value) table exists, read db-specific settings
1009 ** from that table */
1010 if( sqlite3_table_column_metadata(db
,0,"config",0,0,0,0,0,0)==SQLITE_OK
){
1011 rc
= sqlite3_prepare_v2(db
, "SELECT name, value FROM config", -1, &pStmt
, 0);
1012 if( rc
) fatalError("cannot prepare query of CONFIG table: %s",
1013 sqlite3_errmsg(db
));
1014 while( SQLITE_ROW
==sqlite3_step(pStmt
) ){
1015 const char *zName
= (const char *)sqlite3_column_text(pStmt
,0);
1016 if( zName
==0 ) continue;
1017 if( strcmp(zName
, "oss-fuzz")==0 ){
1018 ossFuzzThisDb
= sqlite3_column_int(pStmt
,1);
1019 if( verboseFlag
) printf("Config: oss-fuzz=%d\n", ossFuzzThisDb
);
1021 if( strcmp(zName
, "limit-mem")==0 && !nativeMalloc
){
1022 #if !defined(SQLITE_ENABLE_MEMSYS3) && !defined(SQLITE_ENABLE_MEMSYS5)
1023 fatalError("the limit-mem option requires -DSQLITE_ENABLE_MEMSYS5"
1026 nMemThisDb
= sqlite3_column_int(pStmt
,1);
1027 if( verboseFlag
) printf("Config: limit-mem=%d\n", nMemThisDb
);
1031 sqlite3_finalize(pStmt
);
1035 sqlite3_create_function(db
, "readfile", 1, SQLITE_UTF8
, 0,
1036 readfileFunc
, 0, 0);
1037 rc
= sqlite3_prepare_v2(db
, zInsSql
, -1, &pStmt
, 0);
1038 if( rc
) fatalError("cannot prepare statement [%s]: %s",
1039 zInsSql
, sqlite3_errmsg(db
));
1040 rc
= sqlite3_exec(db
, "BEGIN", 0, 0, 0);
1041 if( rc
) fatalError("cannot start a transaction");
1042 for(i
=iFirstInsArg
; i
<argc
; i
++){
1043 sqlite3_bind_text(pStmt
, 1, argv
[i
], -1, SQLITE_STATIC
);
1044 sqlite3_step(pStmt
);
1045 rc
= sqlite3_reset(pStmt
);
1046 if( rc
) fatalError("insert failed for %s", argv
[i
]);
1048 sqlite3_finalize(pStmt
);
1049 rc
= sqlite3_exec(db
, "COMMIT", 0, 0, 0);
1050 if( rc
) fatalError("cannot commit the transaction: %s", sqlite3_errmsg(db
));
1051 rebuild_database(db
);
1055 rc
= sqlite3_exec(db
, "PRAGMA query_only=1;", 0, 0, 0);
1056 if( rc
) fatalError("cannot set database to query-only");
1057 if( zExpDb
!=0 || zExpSql
!=0 ){
1058 sqlite3_create_function(db
, "writefile", 2, SQLITE_UTF8
, 0,
1059 writefileFunc
, 0, 0);
1062 "SELECT writefile(printf('%s/db%06d.db',?1,dbid),dbcontent),"
1063 " dbid, printf('%s/db%06d.db',?1,dbid), length(dbcontent)"
1064 " FROM db WHERE ?2<0 OR dbid=?2;";
1065 rc
= sqlite3_prepare_v2(db
, zExDb
, -1, &pStmt
, 0);
1066 if( rc
) fatalError("cannot prepare statement [%s]: %s",
1067 zExDb
, sqlite3_errmsg(db
));
1068 sqlite3_bind_text64(pStmt
, 1, zExpDb
, strlen(zExpDb
),
1069 SQLITE_STATIC
, SQLITE_UTF8
);
1070 sqlite3_bind_int(pStmt
, 2, onlyDbid
);
1071 while( sqlite3_step(pStmt
)==SQLITE_ROW
){
1072 printf("write db-%d (%d bytes) into %s\n",
1073 sqlite3_column_int(pStmt
,1),
1074 sqlite3_column_int(pStmt
,3),
1075 sqlite3_column_text(pStmt
,2));
1077 sqlite3_finalize(pStmt
);
1080 const char *zExSql
=
1081 "SELECT writefile(printf('%s/sql%06d.txt',?1,sqlid),sqltext),"
1082 " sqlid, printf('%s/sql%06d.txt',?1,sqlid), length(sqltext)"
1083 " FROM xsql WHERE ?2<0 OR sqlid=?2;";
1084 rc
= sqlite3_prepare_v2(db
, zExSql
, -1, &pStmt
, 0);
1085 if( rc
) fatalError("cannot prepare statement [%s]: %s",
1086 zExSql
, sqlite3_errmsg(db
));
1087 sqlite3_bind_text64(pStmt
, 1, zExpSql
, strlen(zExpSql
),
1088 SQLITE_STATIC
, SQLITE_UTF8
);
1089 sqlite3_bind_int(pStmt
, 2, onlySqlid
);
1090 while( sqlite3_step(pStmt
)==SQLITE_ROW
){
1091 printf("write sql-%d (%d bytes) into %s\n",
1092 sqlite3_column_int(pStmt
,1),
1093 sqlite3_column_int(pStmt
,3),
1094 sqlite3_column_text(pStmt
,2));
1096 sqlite3_finalize(pStmt
);
1102 /* Load all SQL script content and all initial database images from the
1105 blobListLoadFromDb(db
, "SELECT sqlid, sqltext FROM xsql", onlySqlid
,
1106 &g
.nSql
, &g
.pFirstSql
);
1107 if( g
.nSql
==0 ) fatalError("need at least one SQL script");
1108 blobListLoadFromDb(db
, "SELECT dbid, dbcontent FROM db", onlyDbid
,
1109 &g
.nDb
, &g
.pFirstDb
);
1111 g
.pFirstDb
= safe_realloc(0, sizeof(Blob
));
1112 memset(g
.pFirstDb
, 0, sizeof(Blob
));
1114 g
.pFirstDb
->seq
= 0;
1119 /* Print the description, if there is one */
1121 zDbName
= azSrcDb
[iSrcDb
];
1122 i
= (int)strlen(zDbName
) - 1;
1123 while( i
>0 && zDbName
[i
-1]!='/' && zDbName
[i
-1]!='\\' ){ i
--; }
1125 sqlite3_prepare_v2(db
, "SELECT msg FROM readme", -1, &pStmt
, 0);
1126 if( pStmt
&& sqlite3_step(pStmt
)==SQLITE_ROW
){
1127 printf("%s: %s\n", zDbName
, sqlite3_column_text(pStmt
,0));
1129 sqlite3_finalize(pStmt
);
1132 /* Rebuild the database, if requested */
1135 printf("%s: rebuilding... ", zDbName
);
1138 rebuild_database(db
);
1139 if( !quietFlag
) printf("done\n");
1142 /* Close the source database. Verify that no SQLite memory allocations are
1146 if( sqlite3_memory_used()>0 ){
1147 fatalError("SQLite has memory in use before the start of testing");
1150 /* Limit available memory, if requested */
1152 if( nMemThisDb
>0 && !nativeMalloc
){
1153 pHeap
= realloc(pHeap
, nMemThisDb
);
1155 fatalError("failed to allocate %d bytes of heap memory", nMem
);
1157 sqlite3_config(SQLITE_CONFIG_HEAP
, pHeap
, nMemThisDb
, 128);
1160 /* Disable lookaside with the --native-malloc option */
1162 sqlite3_config(SQLITE_CONFIG_LOOKASIDE
, 0, 0);
1165 /* Reset the in-memory virtual filesystem */
1168 /* Run a test using each SQL script against each database.
1170 if( !verboseFlag
&& !quietFlag
) printf("%s:", zDbName
);
1171 for(pSql
=g
.pFirstSql
; pSql
; pSql
=pSql
->pNext
){
1172 for(pDb
=g
.pFirstDb
; pDb
; pDb
=pDb
->pNext
){
1174 const char *zVfs
= "inmem";
1175 sqlite3_snprintf(sizeof(g
.zTestName
), g
.zTestName
, "sqlid=%d,dbid=%d",
1178 printf("%s\n", g
.zTestName
);
1180 }else if( !quietFlag
){
1181 static int prevAmt
= -1;
1182 int idx
= pSql
->seq
*g
.nDb
+ pDb
->id
- 1;
1183 int amt
= idx
*10/(g
.nDb
*g
.nSql
);
1185 printf(" %d%%", amt
*10);
1190 createVFile("main.db", pDb
->sz
, pDb
->a
);
1191 sqlite3_randomness(0,0);
1192 if( ossFuzzThisDb
){
1193 #ifndef SQLITE_OSS_FUZZ
1194 fatalError("--oss-fuzz not supported: recompile with -DSQLITE_OSS_FUZZ");
1196 extern int LLVMFuzzerTestOneInput(const uint8_t*, size_t);
1197 LLVMFuzzerTestOneInput((const uint8_t*)pSql
->a
, (size_t)pSql
->sz
);
1200 openFlags
= SQLITE_OPEN_CREATE
| SQLITE_OPEN_READWRITE
;
1201 if( nativeFlag
&& pDb
->sz
==0 ){
1202 openFlags
|= SQLITE_OPEN_MEMORY
;
1205 rc
= sqlite3_open_v2("main.db", &db
, openFlags
, zVfs
);
1206 if( rc
) fatalError("cannot open inmem database");
1207 sqlite3_limit(db
, SQLITE_LIMIT_LENGTH
, 100000000);
1208 sqlite3_limit(db
, SQLITE_LIMIT_LIKE_PATTERN_LENGTH
, 50);
1209 if( cellSzCkFlag
) runSql(db
, "PRAGMA cell_size_check=ON", runFlags
);
1211 #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
1212 if( sqlFuzz
|| vdbeLimitFlag
){
1213 sqlite3_progress_handler(db
, 100000, progressHandler
, &vdbeLimitFlag
);
1217 runSql(db
, (char*)pSql
->a
, runFlags
);
1218 }while( timeoutTest
);
1220 sqlite3_exec(db
, "PRAGMA temp_store_directory=''", 0, 0, 0);
1223 if( sqlite3_memory_used()>0 ){
1224 fatalError("memory leak: %lld bytes outstanding",
1225 sqlite3_memory_used());
1231 /* Simulate an error if the TEST_FAILURE environment variable is "5".
1232 ** This is used to verify that automated test script really do spot
1233 ** errors that occur in this test program.
1236 if( zFailCode
[0]=='5' && zFailCode
[1]==0 ){
1237 fatalError("simulated failure");
1238 }else if( zFailCode
[0]!=0 ){
1239 /* If TEST_FAILURE is something other than 5, just exit the test
1241 printf("\nExit early due to TEST_FAILURE being set\n");
1243 goto sourcedb_cleanup
;
1248 if( !quietFlag
&& !verboseFlag
){
1249 printf(" 100%% - %d tests\n", g
.nDb
*g
.nSql
);
1252 /* Clean up at the end of processing a single source database
1255 blobListFree(g
.pFirstSql
);
1256 blobListFree(g
.pFirstDb
);
1259 } /* End loop over all source databases */
1262 sqlite3_int64 iElapse
= timeOfDay() - iBegin
;
1263 printf("fuzzcheck: 0 errors out of %d tests in %d.%03d seconds\n"
1265 nTest
, (int)(iElapse
/1000), (int)(iElapse
%1000),
1266 sqlite3_libversion(), sqlite3_sourceid());