Index: third_party/sqlite/src/test/fuzzcheck.c |
diff --git a/third_party/sqlite/src/test/fuzzcheck.c b/third_party/sqlite/src/test/fuzzcheck.c |
index 6d9c745528b41a7f845a1c9da1823a2dba152cb3..75d519566fc81f27cc870a3956a9554843a80798 100644 |
--- a/third_party/sqlite/src/test/fuzzcheck.c |
+++ b/third_party/sqlite/src/test/fuzzcheck.c |
@@ -79,6 +79,11 @@ |
# include <unistd.h> |
#endif |
+#ifdef SQLITE_OSS_FUZZ |
+# include <stddef.h> |
+# include <stdint.h> |
+#endif |
+ |
/* |
** Files in the virtual file system. |
*/ |
@@ -127,6 +132,7 @@ static struct GlobalVars { |
Blob *pFirstDb; /* Content of first template database */ |
int nSql; /* Number of SQL scripts */ |
Blob *pFirstSql; /* First SQL script */ |
+ unsigned int uRandom; /* Seed for the SQLite PRNG */ |
char zTestName[100]; /* Name of current test */ |
} g; |
@@ -188,7 +194,7 @@ static int progressHandler(void *pVdbeLimitFlag){ |
** Reallocate memory. Show and error and quit if unable. |
*/ |
static void *safe_realloc(void *pOld, int szNew){ |
- void *pNew = realloc(pOld, szNew); |
+ void *pNew = realloc(pOld, szNew<=0 ? 1 : szNew); |
if( pNew==0 ) fatalError("unable to realloc for %d bytes", szNew); |
return pNew; |
} |
@@ -255,8 +261,9 @@ static VFile *createVFile(const char *zName, int sz, unsigned char *pData){ |
if( i>=MX_FILE ) return 0; |
pNew = &g.aFile[i]; |
if( zName ){ |
- pNew->zFilename = safe_realloc(0, strlen(zName)+1); |
- memcpy(pNew->zFilename, zName, strlen(zName)+1); |
+ int nName = (int)strlen(zName)+1; |
+ pNew->zFilename = safe_realloc(0, nName); |
+ memcpy(pNew->zFilename, zName, nName); |
}else{ |
pNew->zFilename = 0; |
} |
@@ -588,10 +595,18 @@ static int inmemFullPathname( |
return SQLITE_OK; |
} |
+/* Always use the same random see, for repeatability. |
+*/ |
+static int inmemRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){ |
+ memset(zBuf, 0, nBuf); |
+ memcpy(zBuf, &g.uRandom, nBuf<sizeof(g.uRandom) ? nBuf : sizeof(g.uRandom)); |
+ return nBuf; |
+} |
+ |
/* |
** Register the VFS that reads from the g.aFile[] set of files. |
*/ |
-static void inmemVfsRegister(void){ |
+static void inmemVfsRegister(int makeDefault){ |
static sqlite3_vfs inmemVfs; |
sqlite3_vfs *pDefault = sqlite3_vfs_find(0); |
inmemVfs.iVersion = 3; |
@@ -602,10 +617,10 @@ static void inmemVfsRegister(void){ |
inmemVfs.xDelete = inmemDelete; |
inmemVfs.xAccess = inmemAccess; |
inmemVfs.xFullPathname = inmemFullPathname; |
- inmemVfs.xRandomness = pDefault->xRandomness; |
+ inmemVfs.xRandomness = inmemRandomness; |
inmemVfs.xSleep = pDefault->xSleep; |
inmemVfs.xCurrentTimeInt64 = pDefault->xCurrentTimeInt64; |
- sqlite3_vfs_register(&inmemVfs, 0); |
+ sqlite3_vfs_register(&inmemVfs, makeDefault); |
}; |
/* |
@@ -778,25 +793,25 @@ static void showHelp(void){ |
"Read databases and SQL scripts from SOURCE-DB and execute each script against\n" |
"each database, checking for crashes and memory leaks.\n" |
"Options:\n" |
-" --cell-size-check Set the PRAGMA cell_size_check=ON\n" |
-" --dbid N Use only the database where dbid=N\n" |
-" --export-db DIR Write databases to files(s) in DIR. Works with --dbid\n" |
-" --export-sql DIR Write SQL to file(s) in DIR. Also works with --sqlid\n" |
-" --help Show this help text\n" |
-" -q Reduced output\n" |
-" --quiet Reduced output\n" |
-" --limit-mem N Limit memory used by test SQLite instance to N bytes\n" |
-" --limit-vdbe Panic if an sync SQL runs for more than 100,000 cycles\n" |
-" --load-sql ARGS... Load SQL scripts fro files into SOURCE-DB\n" |
-" --load-db ARGS... Load template databases from files into SOURCE_DB\n" |
-" -m TEXT Add a description to the database\n" |
-" --native-vfs Use the native VFS for initially empty database files\n" |
-" --rebuild Rebuild and vacuum the database file\n" |
-" --result-trace Show the results of each SQL command\n" |
-" --sqlid N Use only SQL where sqlid=N\n" |
-" --timeout N Abort if any single test case needs more than N seconds\n" |
-" -v Increased output\n" |
-" --verbose Increased output\n" |
+" --cell-size-check Set the PRAGMA cell_size_check=ON\n" |
+" --dbid N Use only the database where dbid=N\n" |
+" --export-db DIR Write databases to files(s) in DIR. Works with --dbid\n" |
+" --export-sql DIR Write SQL to file(s) in DIR. Also works with --sqlid\n" |
+" --help Show this help text\n" |
+" -q|--quiet Reduced output\n" |
+" --limit-mem N Limit memory used by test SQLite instance to N bytes\n" |
+" --limit-vdbe Panic if any test runs for more than 100,000 cycles\n" |
+" --load-sql ARGS... Load SQL scripts fro files into SOURCE-DB\n" |
+" --load-db ARGS... Load template databases from files into SOURCE_DB\n" |
+" -m TEXT Add a description to the database\n" |
+" --native-vfs Use the native VFS for initially empty database files\n" |
+" --oss-fuzz Enable OSS-FUZZ testing\n" |
+" --prng-seed N Seed value for the PRGN inside of SQLite\n" |
+" --rebuild Rebuild and vacuum the database file\n" |
+" --result-trace Show the results of each SQL command\n" |
+" --sqlid N Use only SQL where sqlid=N\n" |
+" --timeout N Abort if any single test needs more than N seconds\n" |
+" -v|--verbose Increased output. Repeat for more output.\n" |
); |
} |
@@ -830,9 +845,13 @@ int main(int argc, char **argv){ |
int sqlFuzz = 0; /* True for SQL fuzz testing. False for DB fuzz */ |
int iTimeout = 120; /* Default 120-second timeout */ |
int nMem = 0; /* Memory limit */ |
+ int nMemThisDb = 0; /* Memory limit set by the CONFIG table */ |
char *zExpDb = 0; /* Write Databases to files in this directory */ |
char *zExpSql = 0; /* Write SQL to files in this directory */ |
void *pHeap = 0; /* Heap for use by SQLite */ |
+ int ossFuzz = 0; /* enable OSS-FUZZ testing */ |
+ int ossFuzzThisDb = 0; /* ossFuzz value for this particular database */ |
+ sqlite3_vfs *pDfltVfs; /* The default VFS */ |
iBegin = timeOfDay(); |
#ifdef __unix__ |
@@ -840,6 +859,8 @@ int main(int argc, char **argv){ |
#endif |
g.zArgv0 = argv[0]; |
zFailCode = getenv("TEST_FAILURE"); |
+ pDfltVfs = sqlite3_vfs_find(0); |
+ inmemVfsRegister(1); |
for(i=1; i<argc; i++){ |
const char *z = argv[i]; |
if( z[0]=='-' ){ |
@@ -865,8 +886,13 @@ int main(int argc, char **argv){ |
return 0; |
}else |
if( strcmp(z,"limit-mem")==0 ){ |
+#if !defined(SQLITE_ENABLE_MEMSYS3) && !defined(SQLITE_ENABLE_MEMSYS5) |
+ fatalError("the %s option requires -DSQLITE_ENABLE_MEMSYS5 or _MEMSYS3", |
+ argv[i]); |
+#else |
if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]); |
nMem = integerValue(argv[++i]); |
+#endif |
}else |
if( strcmp(z,"limit-vdbe")==0 ){ |
vdbeLimitFlag = 1; |
@@ -888,6 +914,13 @@ int main(int argc, char **argv){ |
if( strcmp(z,"native-vfs")==0 ){ |
nativeFlag = 1; |
}else |
+ if( strcmp(z,"oss-fuzz")==0 ){ |
+ ossFuzz = 1; |
+ }else |
+ if( strcmp(z,"prng-seed")==0 ){ |
+ if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]); |
+ g.uRandom = atoi(argv[++i]); |
+ }else |
if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){ |
quietFlag = 1; |
verboseFlag = 0; |
@@ -914,8 +947,8 @@ int main(int argc, char **argv){ |
}else |
if( strcmp(z,"verbose")==0 || strcmp(z,"v")==0 ){ |
quietFlag = 0; |
- verboseFlag = 1; |
- runFlags |= SQL_TRACE; |
+ verboseFlag++; |
+ if( verboseFlag>1 ) runFlags |= SQL_TRACE; |
}else |
{ |
fatalError("unknown option: %s", argv[i]); |
@@ -938,7 +971,8 @@ int main(int argc, char **argv){ |
/* Process each source database separately */ |
for(iSrcDb=0; iSrcDb<nSrcDb; iSrcDb++){ |
- rc = sqlite3_open(azSrcDb[iSrcDb], &db); |
+ rc = sqlite3_open_v2(azSrcDb[iSrcDb], &db, |
+ SQLITE_OPEN_READONLY, pDfltVfs->zName); |
if( rc ){ |
fatalError("cannot open source database %s - %s", |
azSrcDb[iSrcDb], sqlite3_errmsg(db)); |
@@ -964,6 +998,34 @@ int main(int argc, char **argv){ |
sqlite3_free(zSql); |
if( rc ) fatalError("cannot change description: %s", sqlite3_errmsg(db)); |
} |
+ ossFuzzThisDb = ossFuzz; |
+ |
+ /* If the CONFIG(name,value) table exists, read db-specific settings |
+ ** from that table */ |
+ if( sqlite3_table_column_metadata(db,0,"config",0,0,0,0,0,0)==SQLITE_OK ){ |
+ rc = sqlite3_prepare_v2(db, "SELECT name, value FROM config", -1, &pStmt, 0); |
+ if( rc ) fatalError("cannot prepare query of CONFIG table: %s", |
+ sqlite3_errmsg(db)); |
+ while( SQLITE_ROW==sqlite3_step(pStmt) ){ |
+ const char *zName = (const char *)sqlite3_column_text(pStmt,0); |
+ if( zName==0 ) continue; |
+ if( strcmp(zName, "oss-fuzz")==0 ){ |
+ ossFuzzThisDb = sqlite3_column_int(pStmt,1); |
+ if( verboseFlag ) printf("Config: oss-fuzz=%d\n", ossFuzzThisDb); |
+ } |
+ if( strcmp(zName, "limit-mem")==0 ){ |
+#if !defined(SQLITE_ENABLE_MEMSYS3) && !defined(SQLITE_ENABLE_MEMSYS5) |
+ fatalError("the limit-mem option requires -DSQLITE_ENABLE_MEMSYS5" |
+ " or _MEMSYS3"); |
+#else |
+ nMemThisDb = sqlite3_column_int(pStmt,1); |
+ if( verboseFlag ) printf("Config: limit-mem=%d\n", nMemThisDb); |
+#endif |
+ } |
+ } |
+ sqlite3_finalize(pStmt); |
+ } |
+ |
if( zInsSql ){ |
sqlite3_create_function(db, "readfile", 1, SQLITE_UTF8, 0, |
readfileFunc, 0, 0); |
@@ -1050,7 +1112,7 @@ int main(int argc, char **argv){ |
/* Print the description, if there is one */ |
if( !quietFlag ){ |
zDbName = azSrcDb[iSrcDb]; |
- i = strlen(zDbName) - 1; |
+ i = (int)strlen(zDbName) - 1; |
while( i>0 && zDbName[i-1]!='/' && zDbName[i-1]!='\\' ){ i--; } |
zDbName += i; |
sqlite3_prepare_v2(db, "SELECT msg FROM readme", -1, &pStmt, 0); |
@@ -1079,19 +1141,17 @@ int main(int argc, char **argv){ |
} |
/* Limit available memory, if requested */ |
- if( nMem>0 ){ |
+ if( nMemThisDb>0 ){ |
sqlite3_shutdown(); |
- pHeap = malloc(nMem); |
+ pHeap = realloc(pHeap, nMemThisDb); |
if( pHeap==0 ){ |
fatalError("failed to allocate %d bytes of heap memory", nMem); |
} |
- sqlite3_config(SQLITE_CONFIG_HEAP, pHeap, nMem, 128); |
+ sqlite3_config(SQLITE_CONFIG_HEAP, pHeap, nMemThisDb, 128); |
} |
- /* Register the in-memory virtual filesystem |
- */ |
+ /* Reset the in-memory virtual filesystem */ |
formatVfs(); |
- inmemVfsRegister(); |
/* Run a test using each SQL script against each database. |
*/ |
@@ -1116,25 +1176,37 @@ int main(int argc, char **argv){ |
} |
} |
createVFile("main.db", pDb->sz, pDb->a); |
- openFlags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE; |
- if( nativeFlag && pDb->sz==0 ){ |
- openFlags |= SQLITE_OPEN_MEMORY; |
- zVfs = 0; |
- } |
- rc = sqlite3_open_v2("main.db", &db, openFlags, zVfs); |
- if( rc ) fatalError("cannot open inmem database"); |
- if( cellSzCkFlag ) runSql(db, "PRAGMA cell_size_check=ON", runFlags); |
- setAlarm(iTimeout); |
+ sqlite3_randomness(0,0); |
+ if( ossFuzzThisDb ){ |
+#ifndef SQLITE_OSS_FUZZ |
+ fatalError("--oss-fuzz not supported: recompile with -DSQLITE_OSS_FUZZ"); |
+#else |
+ extern int LLVMFuzzerTestOneInput(const uint8_t*, size_t); |
+ LLVMFuzzerTestOneInput((const uint8_t*)pSql->a, (size_t)pSql->sz); |
+#endif |
+ }else{ |
+ openFlags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE; |
+ if( nativeFlag && pDb->sz==0 ){ |
+ openFlags |= SQLITE_OPEN_MEMORY; |
+ zVfs = 0; |
+ } |
+ rc = sqlite3_open_v2("main.db", &db, openFlags, zVfs); |
+ if( rc ) fatalError("cannot open inmem database"); |
+ sqlite3_limit(db, SQLITE_LIMIT_LENGTH, 100000000); |
+ sqlite3_limit(db, SQLITE_LIMIT_LIKE_PATTERN_LENGTH, 50); |
+ if( cellSzCkFlag ) runSql(db, "PRAGMA cell_size_check=ON", runFlags); |
+ setAlarm(iTimeout); |
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK |
- if( sqlFuzz || vdbeLimitFlag ){ |
- sqlite3_progress_handler(db, 100000, progressHandler, &vdbeLimitFlag); |
- } |
+ if( sqlFuzz || vdbeLimitFlag ){ |
+ sqlite3_progress_handler(db, 100000, progressHandler, &vdbeLimitFlag); |
+ } |
#endif |
- do{ |
- runSql(db, (char*)pSql->a, runFlags); |
- }while( timeoutTest ); |
- setAlarm(0); |
- sqlite3_close(db); |
+ do{ |
+ runSql(db, (char*)pSql->a, runFlags); |
+ }while( timeoutTest ); |
+ setAlarm(0); |
+ sqlite3_close(db); |
+ } |
if( sqlite3_memory_used()>0 ) fatalError("memory leak"); |
reformatVfs(); |
nTest++; |