Add the --script option to fuzzcheck.

FossilOrigin-Name: 5a9676bd4945ca098652780515e94d04859e73588d9db5558ab42f8b068a9ddb
This commit is contained in:
drh 2021-10-27 12:05:28 +00:00
parent 48b4bf269c
commit 075201e50f
3 changed files with 124 additions and 18 deletions

View File

@ -1,5 +1,5 @@
C Enhance\sfuzzcheck\sso\sthat\sif\san\sargument\sis\san\sordinary\sdisk\sfile\s(not\na\sdatabase)\sit\sis\sread\sin\sand\sprocessed\sas\sa\sscript.
D 2021-10-26T22:36:41.583
C Add\sthe\s--script\soption\sto\sfuzzcheck.
D 2021-10-27T12:05:28.928
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@ -1055,7 +1055,7 @@ F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c
F test/fuzz4.test c229bcdb45518a89e1d208a21343e061503460ac69fae1539320a89f572eb634
F test/fuzz_common.tcl b7197de6ed1ee8250a4f82d67876f4561b42ee8cbbfc6160dcb66331bad3f830
F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2
F test/fuzzcheck.c b19baffbde9f6b8b3084b8ac3d73bf51a6918078eced6df36d8e0138c91bc4f8
F test/fuzzcheck.c c466c078af4476a4f9c6193a9bad5b16966e55bc3c5717b6aa638dea8308c08a
F test/fuzzdata1.db d36e88741b4f23bcbaaf55b006290669d03c6c891cf13c7b3a53bc1b097b693f
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
@ -1929,7 +1929,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 8443a2724f463bd2e14ea3aa337e8987104f63365767ca2b0993f3f3196cff95
R da5eebcdd2e37607fde1f372cc816cab
P 978dc89df521f5855678128b3c0eb503c67c1b97ddb297076e5f2c03d6297605
R 8173569b9fa9f89185b2af54915c96dd
U drh
Z ca83264146ee66b96c9f2eb230ec2598
Z 551daae1722bbf6ff67f95bde9dbd7dc

View File

@ -1 +1 @@
978dc89df521f5855678128b3c0eb503c67c1b97ddb297076e5f2c03d6297605
5a9676bd4945ca098652780515e94d04859e73588d9db5558ab42f8b068a9ddb

View File

@ -302,6 +302,77 @@ static VFile *createVFile(const char *zName, int sz, unsigned char *pData){
return pNew;
}
/* Return true if the line is all zeros */
static int allZero(unsigned char *aLine){
int i;
for(i=0; i<16 && aLine[i]==0; i++){}
return i==16;
}
/*
** Render a database and query as text that can be input into
** the CLI.
*/
static void renderDbSqlForCLI(
FILE *out, /* Write to this file */
const char *zFile, /* Name of the database file */
unsigned char *aDb, /* Database content */
int nDb, /* Number of bytes in aDb[] */
unsigned char *zSql, /* SQL content */
int nSql /* Bytes of SQL */
){
fprintf(out, ".print ******* %s *******\n", zFile);
if( nDb>100 ){
int i, j; /* Loop counters */
int pgsz; /* Size of each page */
int lastPage = 0; /* Last page number shown */
int iPage; /* Current page number */
unsigned char *aLine; /* Single line to display */
unsigned char buf[16]; /* Fake line */
unsigned char bShow[256]; /* Characters ok to display */
memset(bShow, '.', sizeof(bShow));
for(i=' '; i<='~'; i++){
if( i!='{' && i!='}' && i!='"' && i!='\\' ) bShow[i] = i;
}
pgsz = (aDb[16]<<8) | aDb[17];
if( pgsz==0 ) pgsz = 65536;
if( pgsz<512 || (pgsz&(pgsz-1))!=0 ) pgsz = 4096;
fprintf(out,".open --hexdb\n");
fprintf(out,"| size %d pagesize %d filename %s\n",nDb,pgsz,zFile);
for(i=0; i<nDb; i += 16){
if( i+16>nDb ){
memset(buf, 0, sizeof(buf));
memcpy(buf, aDb+i, nDb-i);
aLine = buf;
}else{
aLine = aDb + i;
}
if( allZero(aLine) ) continue;
iPage = i/pgsz + 1;
if( lastPage!=iPage ){
fprintf(out,"| page %d offset %d\n", iPage, (iPage-1)*pgsz);
lastPage = iPage;
}
fprintf(out,"| %5d:", i-(iPage-1)*pgsz);
for(j=0; j<16; j++) fprintf(out," %02x", aLine[j]);
fprintf(out," ");
for(j=0; j<16; j++){
unsigned char c = (unsigned char)aLine[j];
fputc( bShow[c], stdout);
}
fputc('\n', stdout);
}
fprintf(out,"| end %s\n", zFile);
}else{
fprintf(out,".open :memory:\n");
}
fprintf(out,".testctrl prng_seed 1 db\n");
fprintf(out,".testctrl internal_functions\n");
fprintf(out,"%.*s", nSql, zSql);
if( nSql>0 && zSql[nSql-1]!='\n' ) fprintf(out, "\n");
}
/*
** Read the complete content of a file into memory. Add a 0x00 terminator
** and return a pointer to the result.
@ -325,7 +396,7 @@ static char *readFile(const char *zFilename, long *sz){
if( pBuf && 1==fread(pBuf, nIn, 1, in) ){
pBuf[nIn] = 0;
fclose(in);
return pBuf;
return (char*)pBuf;
}
sqlite3_free(pBuf);
*sz = 0;
@ -876,7 +947,13 @@ static int runDbSql(sqlite3 *db, const char *zSql){
}
/* Invoke this routine to run a single test case */
int runCombinedDbSqlInput(const uint8_t *aData, size_t nByte, int iTimeout){
int runCombinedDbSqlInput(
const uint8_t *aData, /* Combined DB+SQL content */
size_t nByte, /* Size of aData in bytes */
int iTimeout, /* Use this timeout */
int bScript, /* If true, just render CLI output */
int iSqlId /* SQL identifier */
){
int rc; /* SQLite API return value */
int iSql; /* Index in aData[] of start of SQL */
unsigned char *aDb = 0; /* Decoded database content */
@ -902,6 +979,14 @@ int runCombinedDbSqlInput(const uint8_t *aData, size_t nByte, int iTimeout){
iSql = decodeDatabase((unsigned char*)aData, (int)nByte, &aDb, &nDb);
if( iSql<0 ) return 0;
nSql = (int)(nByte - iSql);
if( bScript ){
char zName[100];
sqlite3_snprintf(sizeof(zName),zName,"dbsql%06d.db",iSqlId);
renderDbSqlForCLI(stdout, zName, aDb, nDb,
(unsigned char*)(aData+iSql), nSql);
sqlite3_free(aDb);
return 0;
}
if( eVerbosity>=3 ){
printf(
"****** %d-byte input, %d-byte database, %d-byte script "
@ -1005,7 +1090,7 @@ testrun_finished:
if( rc!=SQLITE_OK ){
fprintf(stdout, "sqlite3_close() returns %d\n", rc);
}
if( eVerbosity>=2 ){
if( eVerbosity>=2 && !bScript ){
fprintf(stdout, "Peak memory usages: %f MB\n",
sqlite3_memory_highwater(1) / 1000000.0);
}
@ -1479,6 +1564,7 @@ static void showHelp(void){
" -q|--quiet Reduced output\n"
" --rebuild Rebuild and vacuum the database file\n"
" --result-trace Show the results of each SQL command\n"
" --script Output CLI script instead of running tests\n"
" --skip N Skip the first N test cases\n"
" --spinner Use a spinner to show progress\n"
" --sqlid N Use only SQL where sqlid=N\n"
@ -1508,6 +1594,7 @@ int main(int argc, char **argv){
int vdbeLimitFlag = 0; /* --limit-vdbe */
int infoFlag = 0; /* --info */
int nSkip = 0; /* --skip */
int bScript = 0; /* --script */
int bSpinner = 0; /* True for --spinner */
int timeoutTest = 0; /* undocumented --timeout-test flag */
int runFlags = 0; /* Flags sent to runSql() */
@ -1642,6 +1729,9 @@ int main(int argc, char **argv){
if( strcmp(z,"result-trace")==0 ){
runFlags |= SQL_OUTPUT;
}else
if( strcmp(z,"script")==0 ){
bScript = 1;
}else
if( strcmp(z,"skip")==0 ){
if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
nSkip = atoi(argv[++i]);
@ -1930,7 +2020,7 @@ int main(int argc, char **argv){
}
/* Print the description, if there is one */
if( !quietFlag ){
if( !quietFlag && !bScript ){
zDbName = azSrcDb[iSrcDb];
i = (int)strlen(zDbName) - 1;
while( i>0 && zDbName[i-1]!='/' && zDbName[i-1]!='\\' ){ i--; }
@ -1987,12 +2077,16 @@ int main(int argc, char **argv){
/* Run a test using each SQL script against each database.
*/
if( !verboseFlag && !quietFlag && !bSpinner ) printf("%s:", zDbName);
if( !verboseFlag && !quietFlag && !bSpinner && !bScript ){
printf("%s:", zDbName);
}
for(pSql=g.pFirstSql; pSql; pSql=pSql->pNext){
tmStart = timeOfDay();
if( isDbSql(pSql->a, pSql->sz) ){
sqlite3_snprintf(sizeof(g.zTestName), g.zTestName, "sqlid=%d",pSql->id);
if( bSpinner ){
if( bScript ){
/* No progress output */
}else if( bSpinner ){
int nTotal =g.nSql;
int idx = pSql->seq;
printf("\r%s: %d/%d ", zDbName, idx, nTotal);
@ -2013,10 +2107,10 @@ int main(int argc, char **argv){
if( nSkip>0 ){
nSkip--;
}else{
runCombinedDbSqlInput(pSql->a, pSql->sz, iTimeout);
runCombinedDbSqlInput(pSql->a, pSql->sz, iTimeout, bScript, pSql->id);
}
nTest++;
if( bTimer ){
if( bTimer && !bScript ){
sqlite3_int64 tmEnd = timeOfDay();
printf("%lld %s\n", tmEnd - tmStart, g.zTestName);
}
@ -2029,7 +2123,9 @@ int main(int argc, char **argv){
const char *zVfs = "inmem";
sqlite3_snprintf(sizeof(g.zTestName), g.zTestName, "sqlid=%d,dbid=%d",
pSql->id, pDb->id);
if( bSpinner ){
if( bScript ){
/* No progress output */
}else if( bSpinner ){
int nTotal = g.nDb*g.nSql;
int idx = pSql->seq*g.nDb + pDb->id - 1;
printf("\r%s: %d/%d ", zDbName, idx, nTotal);
@ -2051,6 +2147,14 @@ int main(int argc, char **argv){
nSkip--;
continue;
}
if( bScript ){
char zName[100];
sqlite3_snprintf(sizeof(zName), zName, "db%06d.db",
pDb->id>1 ? pDb->id : pSql->id);
renderDbSqlForCLI(stdout, zName,
pDb->a, pDb->sz, pSql->a, pSql->sz);
continue;
}
createVFile("main.db", pDb->sz, pDb->a);
sqlite3_randomness(0,0);
if( ossFuzzThisDb ){
@ -2123,7 +2227,9 @@ int main(int argc, char **argv){
}
}
}
if( bSpinner ){
if( bScript ){
/* No progress output */
}else if( bSpinner ){
int nTotal = g.nDb*g.nSql;
printf("\r%s: %d/%d \n", zDbName, nTotal, nTotal);
}else if( !quietFlag && !verboseFlag ){
@ -2139,7 +2245,7 @@ int main(int argc, char **argv){
} /* End loop over all source databases */
if( !quietFlag ){
if( !quietFlag && !bScript ){
sqlite3_int64 iElapse = timeOfDay() - iBegin;
printf("fuzzcheck: 0 errors out of %d tests in %d.%03d seconds\n"
"SQLite %s %s\n",