From f94c1902b95bf9f4b963972e9e5090a3d537607e Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 7 Mar 2018 20:48:21 +0000 Subject: [PATCH] Add the sessionfuzz test program and data obtained from a week of running AFL. Automatically run this test program on any "make test" on unix. FossilOrigin-Name: ecaedfe596d4c05546bfd798fdca94aff6a81f55be7b17ddb65fc5547c4b5aa6 --- Makefile.in | 12 +- main.mk | 13 +- manifest | 18 +- manifest.uuid | 2 +- test/sessionfuzz-data1.db | Bin 0 -> 258048 bytes test/sessionfuzz.c | 1010 +++++++++++++++++++++++++++++++++++++ 6 files changed, 1040 insertions(+), 15 deletions(-) create mode 100644 test/sessionfuzz-data1.db create mode 100644 test/sessionfuzz.c diff --git a/Makefile.in b/Makefile.in index 862f397977..96ef34009e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -650,6 +650,9 @@ ossshell$(TEXE): $(TOP)/test/ossfuzz.c $(TOP)/test/ossshell.c sqlite3.c sqlite3. $(LTLINK) -o $@ $(FUZZCHECK_OPT) $(TOP)/test/ossshell.c \ $(TOP)/test/ossfuzz.c sqlite3.c $(TLIBS) +sessionfuzz$(TEXE): $(TOP)/test/sessionfuzz.c sqlite3.c sqlite3.h + $(CC) $(CFLAGS) -I. -o $@ $(TOP)/test/sessionfuzz.c $(TLIBS) + dbfuzz$(TEXE): $(TOP)/test/dbfuzz.c sqlite3.c sqlite3.h $(LTLINK) -o $@ $(DBFUZZ_OPT) $(TOP)/test/dbfuzz.c sqlite3.c $(TLIBS) @@ -1166,14 +1169,17 @@ fulltestonly: $(TESTPROGS) fuzztest ./testfixture$(TEXE) $(TOP)/test/full.test # Fuzz testing -fuzztest: fuzzcheck$(TEXE) $(FUZZDATA) +fuzztest: fuzzcheck$(TEXE) $(FUZZDATA) sessionfuzz$(TEXE) $(TOP)/test/sessionfuzz-data1.db ./fuzzcheck$(TEXE) $(FUZZDATA) + ./sessionfuzz$(TEXE) run $(TOP)/test/sessionfuzz-data1.db -fastfuzztest: fuzzcheck$(TEXE) $(FUZZDATA) +fastfuzztest: fuzzcheck$(TEXE) $(FUZZDATA) sessionfuzz$(TEXE) $(TOP)/test/sessionfuzz-data1.db ./fuzzcheck$(TEXE) --limit-mem 100M $(FUZZDATA) + ./sessionfuzz$(TEXE) run $(TOP)/test/sessionfuzz-data1.db -valgrindfuzz: fuzzcheck$(TEXT) $(FUZZDATA) +valgrindfuzz: fuzzcheck$(TEXT) $(FUZZDATA) sessionfuzz$(TEXE) $(TOP)/test/sessionfuzz-data1.db valgrind ./fuzzcheck$(TEXE) --cell-size-check --limit-mem 10M --timeout 600 $(FUZZDATA) + valgrind ./sessionfuzz$(TEXE) run $(TOP)/test/sessionfuzz-data1.db # The veryquick.test TCL tests. # diff --git a/main.mk b/main.mk index cdbef4e44e..e5722c5827 100644 --- a/main.mk +++ b/main.mk @@ -575,6 +575,9 @@ ossshell$(EXE): $(TOP)/test/ossfuzz.c $(TOP)/test/ossshell.c sqlite3.c sqlite3.h -DSQLITE_ENABLE_MEMSYS5 $(FUZZCHECK_OPT) \ $(TOP)/test/ossfuzz.c $(TOP)/test/ossshell.c sqlite3.c $(TLIBS) $(THREADLIB) +sessionfuzz$(EXE): $(TOP)/test/sessionfuzz.c sqlite3.c sqlite3.h + $(TCC) -o sessionfuzz$(EXE) $(TOP)/test/sessionfuzz.c -lz $(TLIBS) $(THREADLIB) + mptester$(EXE): sqlite3.c $(TOP)/mptest/mptest.c $(TCCX) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \ $(TLIBS) $(THREADLIB) @@ -895,14 +898,17 @@ fulltestonly: $(TESTPROGS) fuzztest queryplantest: testfixture$(EXE) sqlite3$(EXE) ./testfixture$(EXE) $(TOP)/test/permutations.test queryplanner $(TESTOPTS) -fuzztest: fuzzcheck$(EXE) $(FUZZDATA) +fuzztest: fuzzcheck$(EXE) $(FUZZDATA) sessionfuzz$(EXE) $(TOP)/test/sessionfuzz-data1.db ./fuzzcheck$(EXE) $(FUZZDATA) + ./sessionfuzz run $(TOP)/test/sessionfuzz-data1.db -fastfuzztest: fuzzcheck$(EXE) $(FUZZDATA) +fastfuzztest: fuzzcheck$(EXE) $(FUZZDATA) sessionfuzz$(EXE) $(TOP)/test/sessionfuzz-data1.db ./fuzzcheck$(EXE) --limit-mem 100M $(FUZZDATA) + ./sessionfuzz run $(TOP)/test/sessionfuzz-data1.db -valgrindfuzz: fuzzcheck$(EXE) $(FUZZDATA) +valgrindfuzz: fuzzcheck$(EXE) $(FUZZDATA) sessionfuzz$(EXE) $(TOP)/test/sessionfuzz-data1.db valgrind ./fuzzcheck$(EXE) --cell-size-check --limit-mem 10M --timeout 600 $(FUZZDATA) + valgrind ./sessionfuzz run $(TOP)/test/sessionfuzz-data1.db # The veryquick.test TCL tests. # @@ -1066,6 +1072,7 @@ clean: rm -f mptester mptester.exe rm -f fuzzershell fuzzershell.exe rm -f fuzzcheck fuzzcheck.exe + rm -f sessionfuzz rm -f sqldiff sqldiff.exe rm -f fts5.* fts5parse.* rm -f lsm.h lsm1.c diff --git a/manifest b/manifest index c7b99317a7..340c35486e 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -C Update\sthe\sautoconf\sMakefile\sfor\sMSVC. -D 2018-03-07T15:54:39.405 +C Add\sthe\ssessionfuzz\stest\sprogram\sand\sdata\sobtained\sfrom\sa\sweek\sof\srunning\nAFL.\s\sAutomatically\srun\sthis\stest\sprogram\son\sany\s"make\stest"\son\sunix. +D 2018-03-07T20:48:21.666 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea -F Makefile.in 1d5a68043cc4d8a6e45b37e2639b148cdd7973aa75e90ec71e12d55cd95e32c0 +F Makefile.in 7016fc56c6b9bfe5daac4f34be8be38d8c0b5fab79ccbfb764d3b23bf1c6fff3 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 9d5201ef7e4f575d94ec6cd8a29a40ec3e4e150a01903afad385ccde72b30759 F README.md 1d5342ebda97420f114283e604e5fe99b0da939d63b76d492eabbaae23488276 @@ -411,7 +411,7 @@ F ext/userauth/userauth.c 3410be31283abba70255d71fd24734e017a4497f F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk 761e48fd24449071b8f8480449122fa59c052904666f72d803c64ae09b139298 +F main.mk 63668484c95454af7fc04a384da27ac556f27368d6d0c345e405e1677c66768f F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 @@ -1215,6 +1215,8 @@ F test/selectF.test 21c94e6438f76537b72532fa9fd4710cdd455fc3 F test/selectG.test 089f7d3d7e6db91566f00b036cb353107a2cca6220eb1cb264085a836dae8840 F test/server1.test 46803bd3fe8b99b30dbc5ff38ffc756f5c13a118 F test/session.test 78fa2365e93d3663a6e933f86e7afc395adf18be +F test/sessionfuzz-data1.db 1f8d5def831f19b1c74571037f0d53a588ea49a6c4ca2a028fc0c27ef896dbcb +F test/sessionfuzz.c 8167652afa13b6363825151c44ebcad9c993651e84537be94ec58e5004823f3d F test/shared.test 1da9dbad400cee0d93f252ccf76e1ae007a63746 F test/shared2.test 03eb4a8d372e290107d34b6ce1809919a698e879 F test/shared3.test ab693f9b6e156b8bfb2a0ad94f29fe69602a5d38 @@ -1710,7 +1712,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 d6fa938919dbb3fe73ccdd3cbf0e9264d524ed79125f93f977a7d91c425db821 -R 2a9575451278c1a4c315fccdfdca1672 -U mistachkin -Z e57bc875167796d343177373820c09eb +P 36fec7a4a75006d860aaf3ea6707cea25c5e16f2ac05c21c27fde80f3bfeec63 +R e9b5633f22c17863b715b8220bf589aa +U drh +Z 0dea7c28192df29380ebcdd90caa6963 diff --git a/manifest.uuid b/manifest.uuid index 00e217aaf3..2cbb84b4ca 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -36fec7a4a75006d860aaf3ea6707cea25c5e16f2ac05c21c27fde80f3bfeec63 \ No newline at end of file +ecaedfe596d4c05546bfd798fdca94aff6a81f55be7b17ddb65fc5547c4b5aa6 \ No newline at end of file diff --git a/test/sessionfuzz-data1.db b/test/sessionfuzz-data1.db new file mode 100644 index 0000000000000000000000000000000000000000..df10e10bcd7ad96b512dac036861c4e485aa5268 GIT binary patch literal 258048 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 R%*YZYMtM +#include +#include +#include "zlib.h" + +/* +** Implementation of the "sqlar_uncompress(X,SZ)" SQL function +** +** Parameter SZ is interpreted as an integer. If it is less than or +** equal to zero, then this function returns a copy of X. Or, if +** SZ is equal to the size of X when interpreted as a blob, also +** return a copy of X. Otherwise, decompress blob X using zlib +** utility function uncompress() and return the results (another +** blob). +*/ +static void sqlarUncompressFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + uLong nData; + uLongf sz; + + assert( argc==2 ); + sz = sqlite3_value_int(argv[1]); + + if( sz<=0 || sz==(nData = sqlite3_value_bytes(argv[0])) ){ + sqlite3_result_value(context, argv[0]); + }else{ + const Bytef *pData= sqlite3_value_blob(argv[0]); + Bytef *pOut = sqlite3_malloc(sz); + if( Z_OK!=uncompress(pOut, &sz, pData, nData) ){ + sqlite3_result_error(context, "error in uncompress()", -1); + }else{ + sqlite3_result_blob(context, pOut, sz, SQLITE_TRANSIENT); + } + sqlite3_free(pOut); + } +} + + +/* Run a chunk of SQL. If any errors happen, print an error message +** and exit. +*/ +static void runSql(sqlite3 *db, const char *zSql){ + int rc; + char *zErr = 0; + rc = sqlite3_exec(db, zSql, 0, 0, &zErr); + if( rc || zErr ){ + fprintf(stderr, "SQL failed: rc=%d zErr=[%s]\n", rc, zErr); + fprintf(stderr, "SQL: [%s]\n", zSql); + exit(1); + } +} + +/* +** Write buffer to disk +*/ +static void writeFile(const char *zFilename, const void *pData, int nData){ + FILE *out; + int n; + out = fopen(zFilename, "wb"); + if( out==0 ){ + fprintf(stderr, "cannot open \"%s\" for writing\n", zFilename); + exit(1); + } + n = (int)fwrite(pData, 1, nData, out); + fclose(out); + if( n!=nData ){ + fprintf(stderr, "only wrote %d of %d bytes to \"%s\"\n",n,nData,zFilename); + exit(1); + } +} + +/* +** Generate a changeset from session pSess and write it to zFile +*/ +static void makeChangeset(const char *zFile, sqlite3_session *pSess){ + void *pChg; + int nChg; + int rc; + rc = sqlite3session_changeset(pSess, &nChg, &pChg); + if( rc ){ + fprintf(stderr, "sqlite3session_changeset() returned %d\n", rc); + exit(1); + } + writeFile(zFile, pChg, nChg); + sqlite3_free(pChg); +} + +/* +** Read a file from disk. Space to hold the answer is obtained from +** sqlite3_malloc64(). +*/ +static void readFile(const char *zName, void **ppData, int *pnData){ + FILE *in = fopen(zName, "rb"); + long nIn; + size_t nRead; + char *pBuf; + *ppData = 0; + *pnData = 0; + if( in==0 ){ + fprintf(stderr, "Cannot open \"%s\" for reading\n", zName); + exit(1); + } + fseek(in, 0, SEEK_END); + nIn = ftell(in); + rewind(in); + pBuf = sqlite3_malloc64( nIn+1 ); + if( pBuf==0 ){ + fprintf(stderr, "Failed to malloc %lld bytes\n", (sqlite3_int64)(nIn+1)); + exit(1); + } + nRead = fread(pBuf, 1, nIn, in); + fclose(in); + if( nRead!=nIn ){ + fprintf(stderr, "Read only %d of %d bytes from %s\n", (int)nRead, (int)nIn, + zName); + exit(1); + } + pBuf[nIn] = 0; + *pnData = nIn; + *ppData = pBuf; +} + +/* +** The conflict callback +*/ +static int conflictCall( + void *NotUsed, + int eConflict, + sqlite3_changeset_iter *p +){ + (void)NotUsed; + (void)p; + printf("Conflict %d\n", eConflict); + return SQLITE_CHANGESET_OMIT; +} + +/* +** Reset the database file +*/ +static void db_reset(sqlite3 *db){ + unsigned char *pData; + int nData; + int rc; + + nData = sizeof(aDbBytes); + pData = sqlite3_malloc64( nData ); + if( pData==0 ){ + fprintf(stderr, "could not allocate %d bytes\n", nData); + exit(1); + } + memcpy(pData, aDbBytes, nData); + rc = sqlite3_deserialize(db, 0, pData, nData, nData, + SQLITE_DESERIALIZE_FREEONCLOSE | SQLITE_DESERIALIZE_RESIZEABLE); + if( rc ){ + fprintf(stderr, "sqlite3_deserialize() failed with %d: %s\n", + rc, sqlite3_errmsg(db)); + exit(1); + } +} + +/* +** Given a full file pathname, return a pointer to the tail. +** Example: +** +** input: /home/drh/sqlite/abc.db +** output: abc.db +*/ +static const char *fileTail(const char *z){ + const char *zOut = z; + while( z[0] ){ + if( z[0]=='/' && z[1]!=0 ) zOut = &z[1]; + z++; + } + return zOut; +} + +int main(int argc, char **argv){ + const char *zCmd; + sqlite3 *db; + int rc; + sqlite3_session *pSess; + sqlite3_stmt *pStmt; + void *pChgset; + int nChgset; + int bVerbose = 0; + + if( argc<2 ){ + fprintf(stderr, "%s", zHelp); + exit(1); + } + rc = sqlite3_open_v2(":memory:",&db, + SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, "memdb"); + if( rc ){ + fprintf(stderr, "Failed to open :memory: database: %s\n", + sqlite3_errmsg(db)); + exit(1); + } + db_reset(db); + zCmd = argv[1]; + if( strcmp(zCmd, "setup")==0 ){ + if( argc!=2 ){ + fprintf(stdout, "Wrong number of arguments.\n%s", zHelp); + exit(1); + } + runSql(db, zFillSql); + rc = sqlite3session_create(db, "main", &pSess); + if( rc ){ + fprintf(stderr, "sqlite3session_create() returns %d\n", rc); + exit(1); + } + rc = sqlite3session_attach(pSess, 0); + if( rc ){ + fprintf(stderr, "sqlite3session_attach(db,0) returns %d\n", rc); + exit(1); + } + runSql(db, "INSERT INTO t4(z) VALUES('');"); + makeChangeset("c1.txt", pSess); + runSql(db, + "UPDATE t1 SET b=c, c=b WHERE a IN (5,7);\n" + "DELETE FROM t2 WHERE rowid IN (8,2);\n" + "INSERT OR IGNORE INTO t4 SELECT b FROM t1 WHERE b IS TRUE LIMIT 2;"); + makeChangeset("c2.txt", pSess); + runSql(db, "UPDATE t3 SET x=y, y=NULL WHERE rowid IN (1,3);"); + makeChangeset("c3.txt", pSess); + sqlite3session_delete(pSess); + }else + if( strcmp(zCmd, "run")==0 ){ + int i; + if( argc<3 ){ + fprintf(stdout, "Wrong number of arguments.\n%s", zHelp); + exit(1); + } + for(i=2; i= 512 + && memcmp(pChgset, "SQLite format 3", 16)==0 + ){ + sqlite3 *db2; + sqlite3_stmt *pStmt; + int nCase = 0; + /* This file is an SQL Archive containing many changesets */ + if( !bVerbose ){ printf("%s: ", fileTail(argv[i])); fflush(stdout); } + sqlite3_open_v2(":memory:", &db2, + SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE, "memdb"); + sqlite3_deserialize(db2, 0, pChgset, nChgset, nChgset, + SQLITE_DESERIALIZE_READONLY | SQLITE_DESERIALIZE_FREEONCLOSE); + sqlite3_create_function(db2, "sqlar_uncompress", 2, SQLITE_UTF8, 0, + sqlarUncompressFunc, 0, 0); + rc = sqlite3_prepare_v2(db2, "SELECT name, sqlar_uncompress(data,sz)" + " FROM sqlar", -1, &pStmt, 0); + if( rc ){ + fprintf(stderr, "SQL error: %s\n", sqlite3_errmsg(db2)); + exit(1); + } + while( SQLITE_ROW==sqlite3_step(pStmt) ){ + if( bVerbose ){ + printf("%s/%s:", fileTail(argv[i]), sqlite3_column_text(pStmt,0)); + fflush(stdout); + } + runSql(db, "BEGIN"); + pChgset = (unsigned char*)sqlite3_column_blob(pStmt, 1); + nChgset = sqlite3_column_bytes(pStmt, 1); + rc = sqlite3changeset_apply(db, nChgset, pChgset, 0, conflictCall, 0); + if( bVerbose ){ + printf(" Ok. rc=%d\n", rc); + fflush(stdout); + } + runSql(db, "ROLLBACK"); + nCase++; + } + sqlite3_finalize(pStmt); + sqlite3_close(db2); + if( bVerbose ) printf("%s: ", fileTail(argv[i])); + printf(" %d cases, 0 crashes\n", nCase); + fflush(stdout); + }else{ + /* The named file is just an ordinary changeset */ + printf("%s:", fileTail(argv[i])); + fflush(stdout); + runSql(db, "BEGIN"); + rc = sqlite3changeset_apply(db, nChgset, pChgset, 0, conflictCall, 0); + printf(" %d\n", rc); + fflush(stdout); + runSql(db, "ROLLBACK"); + sqlite3_free(pChgset); + } + } + }else + { + fprintf(stderr, "%s", zHelp); + exit(1); + } + rc = sqlite3_prepare_v2(db, "PRAGMA integrity_check;", -1, &pStmt, 0); + if( rc ){ + fprintf(stderr, "SQL error: %s\n", sqlite3_errmsg(db)); + exit(1); + } + if( sqlite3_step(pStmt)!=SQLITE_ROW + || strcmp((const char*)sqlite3_column_text(pStmt,0),"ok")!=0 + ){ + fprintf(stderr, "Integrity check failed!\n"); + do{ + fprintf(stderr, "%s\n", sqlite3_column_text(pStmt,0)); + }while( sqlite3_step(pStmt)==SQLITE_ROW ); + } + sqlite3_finalize(pStmt); + sqlite3_close(db); + if( sqlite3_memory_used()>0 ){ + fprintf(stderr, "memory leak of %lld bytes\n", + sqlite3_memory_used()); + exit(1); + } + return 0; +}