Extend fuzzcheck so that it can process dbsqlfuzz cases. Add a collection
of interesting dbsqlfuzz cases to the standard test suite. FossilOrigin-Name: e2991a7ecf5dd241c4bab7c7cadc4901043fb0c3ea1fac70b684f6d8332677f1
This commit is contained in:
commit
31ab7d8e5c
@ -589,7 +589,8 @@ FUZZDATA = \
|
||||
$(TOP)/test/fuzzdata4.db \
|
||||
$(TOP)/test/fuzzdata5.db \
|
||||
$(TOP)/test/fuzzdata6.db \
|
||||
$(TOP)/test/fuzzdata7.db
|
||||
$(TOP)/test/fuzzdata7.db \
|
||||
$(TOP)/test/fuzzdata8.db
|
||||
|
||||
# Standard options to testfixture
|
||||
#
|
||||
@ -612,6 +613,12 @@ FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
|
||||
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ
|
||||
FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000
|
||||
FUZZCHECK_OPT += -DSQLITE_PRINTF_PRECISION_LIMIT=1000
|
||||
FUZZCHECK_OPT += -DSQLITE_ENABLE_DESERIALIZE
|
||||
FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS4
|
||||
#FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS5
|
||||
FUZZCHECK_OPT += -DSQLITE_ENABLE_RTREE
|
||||
FUZZCHECK_OPT += -DSQLITE_ENABLE_GEOPOLY
|
||||
FUZZCHECK_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
|
||||
FUZZCHECK_SRC = $(TOP)/test/fuzzcheck.c $(TOP)/test/ossfuzz.c
|
||||
DBFUZZ_OPT =
|
||||
|
||||
|
15
Makefile.msc
15
Makefile.msc
@ -1626,7 +1626,8 @@ FUZZDATA = \
|
||||
$(TOP)\test\fuzzdata4.db \
|
||||
$(TOP)\test\fuzzdata5.db \
|
||||
$(TOP)\test\fuzzdata6.db \
|
||||
$(TOP)\test\fuzzdata7.db
|
||||
$(TOP)\test\fuzzdata7.db \
|
||||
$(TOP)\test\fuzzdata8.db
|
||||
# <</mark>>
|
||||
|
||||
# Additional compiler options for the shell. These are only effective
|
||||
@ -1644,7 +1645,13 @@ SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DESERIALIZE=1
|
||||
#
|
||||
MPTESTER_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5
|
||||
FUZZERSHELL_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1
|
||||
FUZZCHECK_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ -DSQLITE_MAX_MEMORY=50000000 -DSQLITE_PRINTF_PRECISION_LIMIT=1000
|
||||
FUZZCHECK_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ -DSQLITE_MAX_MEMORY=50000000 -DSQLITE_PRINTF_PRECISION_LIMIT=1000
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_DESERIALIZE
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_FTS4
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_RTREE
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_GEOPOLY
|
||||
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_DBSTAT_VTAB
|
||||
|
||||
FUZZCHECK_SRC = $(TOP)\test\fuzzcheck.c $(TOP)\test\ossfuzz.c
|
||||
OSSSHELL_SRC = $(TOP)\test\ossshell.c $(TOP)\test\ossfuzz.c
|
||||
DBFUZZ_COMPILE_OPTS = -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION
|
||||
@ -1731,10 +1738,10 @@ dbfuzz.exe: $(TOP)\test\dbfuzz.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) $(DBFUZZ_COMPILE_OPTS) $(TOP)\test\dbfuzz.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
fuzzcheck.exe: $(FUZZCHECK_SRC) $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) $(FUZZCHECK_COMPILE_OPTS) $(FUZZCHECK_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
$(LTLINK) $(NO_WARN) $(FUZZCHECK_OPTS) $(FUZZCHECK_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
ossshell.exe: $(OSSSHELL_SRC) $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) $(FUZZCHECK_COMPILE_OPTS) $(OSSSHELL_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
$(LTLINK) $(NO_WARN) $(FUZZCHECK_OPTS) $(OSSSHELL_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
|
||||
|
||||
sessionfuzz.exe: zlib $(TOP)\test\sessionfuzz.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) -I$(ZLIBINCDIR) $(TOP)\test\sessionfuzz.c /link $(LDFLAGS) $(LTLINKOPTS) /LIBPATH:$(ZLIBLIBDIR) $(ZLIBLIB)
|
||||
|
8
main.mk
8
main.mk
@ -510,7 +510,8 @@ FUZZDATA = \
|
||||
$(TOP)/test/fuzzdata4.db \
|
||||
$(TOP)/test/fuzzdata5.db \
|
||||
$(TOP)/test/fuzzdata6.db \
|
||||
$(TOP)/test/fuzzdata7.db
|
||||
$(TOP)/test/fuzzdata7.db \
|
||||
$(TOP)/test/fuzzdata8.db
|
||||
|
||||
# Standard options to testfixture
|
||||
#
|
||||
@ -531,6 +532,11 @@ FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
|
||||
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5
|
||||
FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000
|
||||
FUZZCHECK_OPT += -DSQLITE_PRINTF_PRECISION_LIMIT=1000
|
||||
FUZZCHECK_OPT += -DSQLITE_ENABLE_DESERIALIZE
|
||||
FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS4
|
||||
FUZZCHECK_OPT += -DSQLITE_ENABLE_RTREE
|
||||
FUZZCHECK_OPT += -DSQLITE_ENABLE_GEOPOLY
|
||||
FUZZCHECK_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
|
||||
DBFUZZ_OPT =
|
||||
KV_OPT = -DSQLITE_THREADSAFE=0 -DSQLITE_DIRECT_OVERFLOW_READ
|
||||
ST_OPT = -DSQLITE_THREADSAFE=0
|
||||
|
24
manifest
24
manifest
@ -1,10 +1,10 @@
|
||||
C Fix\sa\scouple\sof\sassert()\sstatments\sin\sbtree.c\sthat\scould\sfail\swith\scorrupt\sdatabases.
|
||||
D 2019-01-25T13:42:12.343
|
||||
C Extend\sfuzzcheck\sso\sthat\sit\scan\sprocess\sdbsqlfuzz\scases.\sAdd\sa\scollection\nof\sinteresting\sdbsqlfuzz\scases\sto\sthe\sstandard\stest\ssuite.
|
||||
D 2019-01-25T14:23:36.115
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F Makefile.in 0e7c107ebcaff26681bc5bcf017557db85aa828d6f7fd652d748b7a78072c298
|
||||
F Makefile.in 9947eae873c07ae894d4c8633b76c0a0daca7b9fd54401096a77d1a6c7b74359
|
||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||
F Makefile.msc e04060b2138cefc198809d7adad70aebb4a667520b9133fe07a90a1769522dc7
|
||||
F Makefile.msc 5df60c70edb157feb2148a14c687551969599bd065875a0b959b6b139721ca72
|
||||
F README.md 377233394b905d3b2e2b33741289e093bc93f2e7adbe00923b2c5958c9a9edee
|
||||
F VERSION 453e2f4529ca208196d5567db28d549d7151f79efd33f6e6cfe6e613e583a0be
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
@ -436,7 +436,7 @@ F ext/userauth/userauth.c f81aa5a3ecacf406f170c62a144405858f6f6de51dbdc0920134e6
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
|
||||
F main.mk 468c42acafaf69ae8d514d40cae78343b1d825aabd82e0368f6a3bcf8e4d2469
|
||||
F main.mk e28b19556f75ba6e841fc9c883d6a3c16edeae2d16d4edf32bf3c150725fc4d8
|
||||
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
|
||||
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
|
||||
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
|
||||
@ -485,7 +485,7 @@ F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
|
||||
F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
|
||||
F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a
|
||||
F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944
|
||||
F src/memdb.c 6099be387f1161e07b20e5ea5118348a6fb7eb55edcb487d6bea15ee917b37e4
|
||||
F src/memdb.c d95f6ad26f7c582026c5501b32dc0201ce781ad496bc61107d759b5e4e5c563a
|
||||
F src/memjournal.c 6f3d36a0a8f72f48f6c3c722f04301ac64f2515435fa42924293e46fc7994661
|
||||
F src/msvc.h 4942752b6a253116baaa8de75256c51a459a5e81
|
||||
F src/mutex.c bae36f8af32c22ad80bbf0ccebec63c252b6a2b86e4d3e42672ff287ebf4a604
|
||||
@ -984,7 +984,7 @@ F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c
|
||||
F test/fuzz4.test c229bcdb45518a89e1d208a21343e061503460ac69fae1539320a89f572eb634
|
||||
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
|
||||
F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2
|
||||
F test/fuzzcheck.c 6edb2a0b6c8113cdac10f8e35b891be1a1b08ebacb1c2e2f93876d4d056e8e15
|
||||
F test/fuzzcheck.c b72e92f38747e4fe45b4df41a750a9ee3797f28e808c11b753d91d750a559c51
|
||||
F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664
|
||||
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
|
||||
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
|
||||
@ -992,6 +992,7 @@ F test/fuzzdata4.db b502c7d5498261715812dd8b3c2005bad08b3a26e6489414bd13926cd3e4
|
||||
F test/fuzzdata5.db e35f64af17ec48926481cfaf3b3855e436bd40d1cfe2d59a9474cb4b748a52a5
|
||||
F test/fuzzdata6.db 92a80e4afc172c24f662a10a612d188fb272de4a9bd19e017927c95f737de6d7
|
||||
F test/fuzzdata7.db 3fc78e65dfe0be9df9e262075d5a335f18f627da47dfc691d1a7b822f34d4b99
|
||||
F test/fuzzdata8.db 8a96892bd2535578ff2ca27db823b7e149cfce6694c15ca80521fa758be605b1
|
||||
F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8
|
||||
F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14
|
||||
F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
|
||||
@ -1802,7 +1803,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P d0d5689371577b2861d4a9464443d055f3256f3f51d89e0388233a4cbe2601ee
|
||||
R 86e5fe4bfae1d318cbbdc2a84c65ab72
|
||||
U dan
|
||||
Z 4fafd1aea85fe91f1dc4e55e3b1f6edd
|
||||
P 5eb5e8289fa71e5e29e081d33d4a59c64b463bf6b06d7070c05c46d77d808ad4 2c1ef40e787a6bc355b50168527a47eb09acd30d0d88cff8336a434ad554115d
|
||||
R a2806326e0cb0598d45e4cc4f8c04ac5
|
||||
T +closed 2c1ef40e787a6bc355b50168527a47eb09acd30d0d88cff8336a434ad554115d
|
||||
U drh
|
||||
Z e0264b6bc0795e1cb58dfca1c59c35f8
|
||||
|
@ -1 +1 @@
|
||||
5eb5e8289fa71e5e29e081d33d4a59c64b463bf6b06d7070c05c46d77d808ad4
|
||||
e2991a7ecf5dd241c4bab7c7cadc4901043fb0c3ea1fac70b684f6d8332677f1
|
@ -310,8 +310,13 @@ static int memdbFetch(
|
||||
void **pp
|
||||
){
|
||||
MemFile *p = (MemFile *)pFile;
|
||||
p->nMmap++;
|
||||
*pp = (void*)(p->aData + iOfst);
|
||||
if( iOfst+iAmt>p->sz ){
|
||||
assert( CORRUPT_DB );
|
||||
*pp = 0;
|
||||
}else{
|
||||
p->nMmap++;
|
||||
*pp = (void*)(p->aData + iOfst);
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
507
test/fuzzcheck.c
507
test/fuzzcheck.c
@ -69,6 +69,7 @@
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include "sqlite3.h"
|
||||
#define ISSPACE(X) isspace((unsigned char)(X))
|
||||
#define ISDIGIT(X) isdigit((unsigned char)(X))
|
||||
@ -400,7 +401,6 @@ static void blobListFree(Blob *p){
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Return the current wall-clock time */
|
||||
static sqlite3_int64 timeOfDay(void){
|
||||
static sqlite3_vfs *clockVfs = 0;
|
||||
@ -419,6 +419,458 @@ static sqlite3_int64 timeOfDay(void){
|
||||
return t;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
** Code to process combined database+SQL scripts generated by the
|
||||
** dbsqlfuzz fuzzer.
|
||||
*/
|
||||
|
||||
/* An instance of the following object is passed by pointer as the
|
||||
** client data to various callbacks.
|
||||
*/
|
||||
typedef struct FuzzCtx {
|
||||
sqlite3 *db; /* The database connection */
|
||||
sqlite3_int64 iCutoffTime; /* Stop processing at this time. */
|
||||
sqlite3_int64 iLastCb; /* Time recorded for previous progress callback */
|
||||
sqlite3_int64 mxInterval; /* Longest interval between two progress calls */
|
||||
unsigned nCb; /* Number of progress callbacks */
|
||||
unsigned mxCb; /* Maximum number of progress callbacks allowed */
|
||||
unsigned execCnt; /* Number of calls to the sqlite3_exec callback */
|
||||
int timeoutHit; /* True when reaching a timeout */
|
||||
} FuzzCtx;
|
||||
|
||||
/* Verbosity level for the dbsqlfuzz test runner */
|
||||
static int eVerbosity = 0;
|
||||
|
||||
/* True to activate PRAGMA vdbe_debug=on */
|
||||
static int bVdbeDebug = 0;
|
||||
|
||||
/* Timeout for each fuzzing attempt, in milliseconds */
|
||||
static int iTimeout = 10000; /* Defaults to 10 seconds */
|
||||
|
||||
/* Maximum number of progress handler callbacks */
|
||||
static unsigned int mxProgressCb = 2000;
|
||||
|
||||
/* Maximum string length in SQLite */
|
||||
static int lengthLimit = 1000000;
|
||||
|
||||
/* Maximum byte-code program length in SQLite */
|
||||
static int vdbeOpLimit = 25000;
|
||||
|
||||
/* Maximum size of the in-memory database */
|
||||
static sqlite3_int64 maxDbSize = 104857600;
|
||||
|
||||
/*
|
||||
** Translate a single byte of Hex into an integer.
|
||||
** This routine only works if h really is a valid hexadecimal
|
||||
** character: 0..9a..fA..F
|
||||
*/
|
||||
static unsigned int hexToInt(unsigned int h){
|
||||
#ifdef SQLITE_EBCDIC
|
||||
h += 9*(1&~(h>>4)); /* EBCDIC */
|
||||
#else
|
||||
h += 9*(1&(h>>6)); /* ASCII */
|
||||
#endif
|
||||
return h & 0xf;
|
||||
}
|
||||
|
||||
/*
|
||||
** The first character of buffer zIn[0..nIn-1] is a '['. This routine
|
||||
** checked to see if the buffer holds "[NNNN]" or "[+NNNN]" and if it
|
||||
** does it makes corresponding changes to the *pK value and *pI value
|
||||
** and returns true. If the input buffer does not match the patterns,
|
||||
** no changes are made to either *pK or *pI and this routine returns false.
|
||||
*/
|
||||
static int isOffset(
|
||||
const unsigned char *zIn, /* Text input */
|
||||
int nIn, /* Bytes of input */
|
||||
unsigned int *pK, /* half-byte cursor to adjust */
|
||||
unsigned int *pI /* Input index to adjust */
|
||||
){
|
||||
int i;
|
||||
unsigned int k = 0;
|
||||
unsigned char c;
|
||||
for(i=1; i<nIn && (c = zIn[i])!=']'; i++){
|
||||
if( !isxdigit(c) ) return 0;
|
||||
k = k*16 + hexToInt(c);
|
||||
}
|
||||
if( i==nIn ) return 0;
|
||||
*pK = 2*k;
|
||||
*pI += i;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
** Decode the text starting at zIn into a binary database file.
|
||||
** The maximum length of zIn is nIn bytes. Compute the binary database
|
||||
** file contain in space obtained from sqlite3_malloc().
|
||||
**
|
||||
** Return the number of bytes of zIn consumed. Or return -1 if there
|
||||
** is an error. One potential error is that the recipe specifies a
|
||||
** database file larger than MX_FILE_SZ bytes.
|
||||
**
|
||||
** Abort on an OOM.
|
||||
*/
|
||||
static int decodeDatabase(
|
||||
const unsigned char *zIn, /* Input text to be decoded */
|
||||
int nIn, /* Bytes of input text */
|
||||
unsigned char **paDecode, /* OUT: decoded database file */
|
||||
int *pnDecode /* OUT: Size of decoded database */
|
||||
){
|
||||
unsigned char *a; /* Database under construction */
|
||||
int mx = 0; /* Current size of the database */
|
||||
sqlite3_uint64 nAlloc = 4096; /* Space allocated in a[] */
|
||||
unsigned int i; /* Next byte of zIn[] to read */
|
||||
unsigned int j; /* Temporary integer */
|
||||
unsigned int k; /* half-byte cursor index for output */
|
||||
unsigned int n; /* Number of bytes of input */
|
||||
unsigned char b = 0;
|
||||
if( nIn<4 ) return -1;
|
||||
n = (unsigned int)nIn;
|
||||
a = sqlite3_malloc( nAlloc );
|
||||
if( a==0 ){
|
||||
fprintf(stderr, "Out of memory!\n");
|
||||
exit(1);
|
||||
}
|
||||
memset(a, 0, nAlloc);
|
||||
for(i=k=0; i<n; i++){
|
||||
char c = zIn[i];
|
||||
if( isxdigit(c) ){
|
||||
k++;
|
||||
if( k & 1 ){
|
||||
b = hexToInt(c)*16;
|
||||
}else{
|
||||
b += hexToInt(c);
|
||||
j = k/2 - 1;
|
||||
if( j>=nAlloc ){
|
||||
sqlite3_uint64 newSize;
|
||||
if( nAlloc==MX_FILE_SZ || j>=MX_FILE_SZ ){
|
||||
if( eVerbosity ){
|
||||
fprintf(stderr, "Input database too big: max %d bytes\n",
|
||||
MX_FILE_SZ);
|
||||
}
|
||||
sqlite3_free(a);
|
||||
return -1;
|
||||
}
|
||||
newSize = nAlloc*2;
|
||||
if( newSize<=j ){
|
||||
newSize = (j+4096)&~4095;
|
||||
}
|
||||
if( newSize>MX_FILE_SZ ){
|
||||
if( j>=MX_FILE_SZ ){
|
||||
sqlite3_free(a);
|
||||
return -1;
|
||||
}
|
||||
newSize = MX_FILE_SZ;
|
||||
}
|
||||
a = sqlite3_realloc( a, newSize );
|
||||
if( a==0 ){
|
||||
fprintf(stderr, "Out of memory!\n");
|
||||
exit(1);
|
||||
}
|
||||
assert( newSize > nAlloc );
|
||||
memset(a+nAlloc, 0, newSize - nAlloc);
|
||||
nAlloc = newSize;
|
||||
}
|
||||
if( j>=(unsigned)mx ){
|
||||
mx = (j + 4095)&~4095;
|
||||
if( mx>MX_FILE_SZ ) mx = MX_FILE_SZ;
|
||||
}
|
||||
assert( j<nAlloc );
|
||||
a[j] = b;
|
||||
}
|
||||
}else if( zIn[i]=='[' && i<n-3 && isOffset(zIn+i, nIn-i, &k, &i) ){
|
||||
continue;
|
||||
}else if( zIn[i]=='\n' && i<n-4 && memcmp(zIn+i,"\n--\n",4)==0 ){
|
||||
i += 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*pnDecode = mx;
|
||||
*paDecode = a;
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
** Progress handler callback.
|
||||
**
|
||||
** The argument is the cutoff-time after which all processing should
|
||||
** stop. So return non-zero if the cut-off time is exceeded.
|
||||
*/
|
||||
static int progress_handler(void *pClientData) {
|
||||
FuzzCtx *p = (FuzzCtx*)pClientData;
|
||||
sqlite3_int64 iNow = timeOfDay();
|
||||
int rc = iNow>=p->iCutoffTime;
|
||||
sqlite3_int64 iDiff = iNow - p->iLastCb;
|
||||
if( iDiff > p->mxInterval ) p->mxInterval = iDiff;
|
||||
p->nCb++;
|
||||
if( rc==0 && p->mxCb>0 && p->mxCb<=p->nCb ) rc = 1;
|
||||
if( rc && !p->timeoutHit && eVerbosity>=2 ){
|
||||
printf("Timeout on progress callback %d\n", p->nCb);
|
||||
fflush(stdout);
|
||||
p->timeoutHit = 1;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Disallow debugging pragmas such as "PRAGMA vdbe_debug" and
|
||||
** "PRAGMA parser_trace" since they can dramatically increase the
|
||||
** amount of output without actually testing anything useful.
|
||||
**
|
||||
** Also block ATTACH and DETACH
|
||||
*/
|
||||
static int block_troublesome_sql(
|
||||
void *Notused,
|
||||
int eCode,
|
||||
const char *zArg1,
|
||||
const char *zArg2,
|
||||
const char *zArg3,
|
||||
const char *zArg4
|
||||
){
|
||||
(void)Notused;
|
||||
(void)zArg2;
|
||||
(void)zArg3;
|
||||
(void)zArg4;
|
||||
if( eCode==SQLITE_PRAGMA ){
|
||||
if( sqlite3_strnicmp("vdbe_", zArg1, 5)==0
|
||||
|| sqlite3_stricmp("parser_trace", zArg1)==0
|
||||
|| sqlite3_stricmp("temp_store_directory", zArg1)==0
|
||||
){
|
||||
return SQLITE_DENY;
|
||||
}
|
||||
}else if( (eCode==SQLITE_ATTACH || eCode==SQLITE_DETACH)
|
||||
&& zArg1 && zArg1[0] ){
|
||||
return SQLITE_DENY;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Run the SQL text
|
||||
*/
|
||||
static int runDbSql(sqlite3 *db, const char *zSql){
|
||||
int rc;
|
||||
sqlite3_stmt *pStmt;
|
||||
while( isspace(zSql[0]) ) zSql++;
|
||||
if( zSql[0]==0 ) return SQLITE_OK;
|
||||
if( eVerbosity>=4 ){
|
||||
printf("RUNNING-SQL: [%s]\n", zSql);
|
||||
fflush(stdout);
|
||||
}
|
||||
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
|
||||
if( eVerbosity>=5 ){
|
||||
int j;
|
||||
for(j=0; j<sqlite3_column_count(pStmt); j++){
|
||||
if( j ) printf(",");
|
||||
switch( sqlite3_column_type(pStmt, j) ){
|
||||
case SQLITE_NULL: {
|
||||
printf("NULL");
|
||||
break;
|
||||
}
|
||||
case SQLITE_INTEGER:
|
||||
case SQLITE_FLOAT: {
|
||||
printf("%s", sqlite3_column_text(pStmt, j));
|
||||
break;
|
||||
}
|
||||
case SQLITE_BLOB: {
|
||||
int n = sqlite3_column_bytes(pStmt, j);
|
||||
int i;
|
||||
const unsigned char *a;
|
||||
a = (const unsigned char*)sqlite3_column_blob(pStmt, j);
|
||||
printf("x'");
|
||||
for(i=0; i<n; i++){
|
||||
printf("%02x", a[i]);
|
||||
}
|
||||
printf("'");
|
||||
break;
|
||||
}
|
||||
case SQLITE_TEXT: {
|
||||
int n = sqlite3_column_bytes(pStmt, j);
|
||||
int i;
|
||||
const unsigned char *a;
|
||||
a = (const unsigned char*)sqlite3_column_blob(pStmt, j);
|
||||
printf("'");
|
||||
for(i=0; i<n; i++){
|
||||
if( a[i]=='\'' ){
|
||||
printf("''");
|
||||
}else{
|
||||
putchar(a[i]);
|
||||
}
|
||||
}
|
||||
printf("'");
|
||||
break;
|
||||
}
|
||||
} /* End switch() */
|
||||
} /* End for() */
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
} /* End if( eVerbosity>=5 ) */
|
||||
} /* End while( SQLITE_ROW */
|
||||
if( rc!=SQLITE_DONE && eVerbosity>=4 ){
|
||||
printf("SQL-ERROR: (%d) %s\n", rc, sqlite3_errmsg(db));
|
||||
fflush(stdout);
|
||||
}
|
||||
}else if( eVerbosity>=4 ){
|
||||
printf("SQL-ERROR (%d): %s\n", rc, sqlite3_errmsg(db));
|
||||
fflush(stdout);
|
||||
} /* End if( SQLITE_OK ) */
|
||||
return sqlite3_finalize(pStmt);
|
||||
}
|
||||
|
||||
/* Invoke this routine to run a single test case */
|
||||
int runCombinedDbSqlInput(const uint8_t *aData, size_t nByte){
|
||||
int rc; /* SQLite API return value */
|
||||
int iSql; /* Index in aData[] of start of SQL */
|
||||
unsigned char *aDb = 0; /* Decoded database content */
|
||||
int nDb = 0; /* Size of the decoded database */
|
||||
int i; /* Loop counter */
|
||||
int j; /* Start of current SQL statement */
|
||||
char *zSql = 0; /* SQL text to run */
|
||||
int nSql; /* Bytes of SQL text */
|
||||
FuzzCtx cx; /* Fuzzing context */
|
||||
|
||||
if( nByte<10 ) return 0;
|
||||
if( sqlite3_initialize() ) return 0;
|
||||
if( sqlite3_memory_used()!=0 ){
|
||||
int nAlloc = 0;
|
||||
int nNotUsed = 0;
|
||||
sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &nAlloc, &nNotUsed, 0);
|
||||
fprintf(stderr,"Memory leak in mutator: %lld bytes in %d allocations\n",
|
||||
sqlite3_memory_used(), nAlloc);
|
||||
exit(1);
|
||||
}
|
||||
memset(&cx, 0, sizeof(cx));
|
||||
iSql = decodeDatabase((unsigned char*)aData, (int)nByte, &aDb, &nDb);
|
||||
if( iSql<0 ) return 0;
|
||||
nSql = nByte - iSql;
|
||||
if( eVerbosity>=3 ){
|
||||
printf(
|
||||
"****** %d-byte input, %d-byte database, %d-byte script "
|
||||
"******\n", (int)nByte, nDb, nSql);
|
||||
fflush(stdout);
|
||||
}
|
||||
rc = sqlite3_open(0, &cx.db);
|
||||
if( rc ) return 1;
|
||||
if( bVdbeDebug ){
|
||||
sqlite3_exec(cx.db, "PRAGMA vdbe_debug=ON", 0, 0, 0);
|
||||
}
|
||||
|
||||
/* Invoke the progress handler frequently to check to see if we
|
||||
** are taking too long. The progress handler will return true
|
||||
** (which will block further processing) if more than iTimeout seconds have
|
||||
** elapsed since the start of the test.
|
||||
*/
|
||||
cx.iLastCb = timeOfDay();
|
||||
cx.iCutoffTime = cx.iLastCb + iTimeout; /* Now + iTimeout seconds */
|
||||
cx.mxCb = mxProgressCb;
|
||||
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
|
||||
sqlite3_progress_handler(cx.db, 10, progress_handler, (void*)&cx);
|
||||
#endif
|
||||
|
||||
/* Set a limit on the maximum size of a prepared statement, and the
|
||||
** maximum length of a string or blob */
|
||||
if( vdbeOpLimit>0 ){
|
||||
sqlite3_limit(cx.db, SQLITE_LIMIT_VDBE_OP, vdbeOpLimit);
|
||||
}
|
||||
if( lengthLimit>0 ){
|
||||
sqlite3_limit(cx.db, SQLITE_LIMIT_LENGTH, lengthLimit);
|
||||
}
|
||||
|
||||
if( nDb>=20 && aDb[18]==2 && aDb[19]==2 ){
|
||||
aDb[18] = aDb[19] = 1;
|
||||
}
|
||||
rc = sqlite3_deserialize(cx.db, "main", aDb, nDb, nDb,
|
||||
SQLITE_DESERIALIZE_RESIZEABLE |
|
||||
SQLITE_DESERIALIZE_FREEONCLOSE);
|
||||
if( rc ){
|
||||
fprintf(stderr, "sqlite3_deserialize() failed with %d\n", rc);
|
||||
goto testrun_finished;
|
||||
}
|
||||
if( maxDbSize>0 ){
|
||||
sqlite3_int64 x = maxDbSize;
|
||||
sqlite3_file_control(cx.db, "main", SQLITE_FCNTL_SIZE_LIMIT, &x);
|
||||
}
|
||||
|
||||
/* For high debugging levels, turn on debug mode */
|
||||
if( eVerbosity>=5 ){
|
||||
sqlite3_exec(cx.db, "PRAGMA vdbe_debug=ON;", 0, 0, 0);
|
||||
}
|
||||
|
||||
/* Block debug pragmas and ATTACH/DETACH. But wait until after
|
||||
** deserialize to do this because deserialize depends on ATTACH */
|
||||
sqlite3_set_authorizer(cx.db, block_troublesome_sql, 0);
|
||||
|
||||
/* Consistent PRNG seed */
|
||||
sqlite3_randomness(0,0);
|
||||
|
||||
zSql = sqlite3_malloc( nSql + 1 );
|
||||
if( zSql==0 ){
|
||||
fprintf(stderr, "Out of memory!\n");
|
||||
}else{
|
||||
memcpy(zSql, aData+iSql, nSql);
|
||||
zSql[nSql] = 0;
|
||||
for(i=j=0; zSql[i]; i++){
|
||||
if( zSql[i]==';' ){
|
||||
char cSaved = zSql[i+1];
|
||||
zSql[i+1] = 0;
|
||||
if( sqlite3_complete(zSql+j) ){
|
||||
rc = runDbSql(cx.db, zSql+j);
|
||||
j = i+1;
|
||||
}
|
||||
zSql[i+1] = cSaved;
|
||||
if( rc==SQLITE_INTERRUPT || progress_handler(&cx) ){
|
||||
goto testrun_finished;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( j<i ){
|
||||
runDbSql(cx.db, zSql+j);
|
||||
}
|
||||
}
|
||||
testrun_finished:
|
||||
sqlite3_free(zSql);
|
||||
rc = sqlite3_close(cx.db);
|
||||
if( rc!=SQLITE_OK ){
|
||||
fprintf(stdout, "sqlite3_close() returns %d\n", rc);
|
||||
}
|
||||
if( eVerbosity>=2 ){
|
||||
fprintf(stdout, "Peak memory usages: %f MB\n",
|
||||
sqlite3_memory_highwater(1) / 1000000.0);
|
||||
}
|
||||
if( sqlite3_memory_used()!=0 ){
|
||||
int nAlloc = 0;
|
||||
int nNotUsed = 0;
|
||||
sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &nAlloc, &nNotUsed, 0);
|
||||
fprintf(stderr,"Memory leak: %lld bytes in %d allocations\n",
|
||||
sqlite3_memory_used(), nAlloc);
|
||||
exit(1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** END of the dbsqlfuzz code
|
||||
***************************************************************************/
|
||||
|
||||
/* Look at a SQL text and try to determine if it begins with a database
|
||||
** description, such as would be found in a dbsqlfuzz test case. Return
|
||||
** true if this does appear to be a dbsqlfuzz test case and false otherwise.
|
||||
*/
|
||||
static int isDbSql(unsigned char *a, int n){
|
||||
unsigned char buf[12];
|
||||
int i;
|
||||
if( n>4 && memcmp(a,"\n--\n",4)==0 ) return 1;
|
||||
while( n>0 && isspace(a[0]) ){ a++; n--; }
|
||||
for(i=0; n>0 && i<8; n--, a++){
|
||||
if( isxdigit(a[0]) ) buf[i++] = a[0];
|
||||
}
|
||||
if( i==8 && memcmp(buf,"53514c69",8)==0 ) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Methods for the VHandle object
|
||||
*/
|
||||
static int inmemClose(sqlite3_file *pFile){
|
||||
@ -795,6 +1247,19 @@ static int integerValue(const char *zArg){
|
||||
return (int)(isNeg? -v : v);
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the number of "v" characters in a string. Return 0 if there
|
||||
** are any characters in the string other than "v".
|
||||
*/
|
||||
static int numberOfVChar(const char *z){
|
||||
int N = 0;
|
||||
while( z[0] && z[0]=='v' ){
|
||||
z++;
|
||||
N++;
|
||||
}
|
||||
return z[0]==0 ? N : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Print sketchy documentation for this utility program
|
||||
*/
|
||||
@ -868,6 +1333,7 @@ int main(int argc, char **argv){
|
||||
int nativeMalloc = 0; /* Turn off MEMSYS3/5 and lookaside if true */
|
||||
sqlite3_vfs *pDfltVfs; /* The default VFS */
|
||||
int openFlags4Data; /* Flags for sqlite3_open_v2() */
|
||||
int nV; /* How much to increase verbosity with -vvvv */
|
||||
|
||||
sqlite3_initialize();
|
||||
iBegin = timeOfDay();
|
||||
@ -951,6 +1417,7 @@ int main(int argc, char **argv){
|
||||
if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){
|
||||
quietFlag = 1;
|
||||
verboseFlag = 0;
|
||||
eVerbosity = 0;
|
||||
}else
|
||||
if( strcmp(z,"rebuild")==0 ){
|
||||
rebuildFlag = 1;
|
||||
@ -973,11 +1440,27 @@ int main(int argc, char **argv){
|
||||
fatalError("timeout is not available on non-unix systems");
|
||||
#endif
|
||||
}else
|
||||
if( strcmp(z,"verbose")==0 || strcmp(z,"v")==0 ){
|
||||
if( strcmp(z,"verbose")==0 ){
|
||||
quietFlag = 0;
|
||||
verboseFlag++;
|
||||
eVerbosity++;
|
||||
if( verboseFlag>1 ) runFlags |= SQL_TRACE;
|
||||
}else
|
||||
if( (nV = numberOfVChar(z))>=1 ){
|
||||
quietFlag = 0;
|
||||
verboseFlag += nV;
|
||||
eVerbosity += nV;
|
||||
if( verboseFlag>1 ) runFlags |= SQL_TRACE;
|
||||
}else
|
||||
if( strcmp(z,"version")==0 ){
|
||||
int ii;
|
||||
const char *z;
|
||||
printf("SQLite %s %s\n", sqlite3_libversion(), sqlite3_sourceid());
|
||||
for(ii=0; (z = sqlite3_compileoption_get(ii))!=0; ii++){
|
||||
printf("%s\n", z);
|
||||
}
|
||||
return 0;
|
||||
}else
|
||||
{
|
||||
fatalError("unknown option: %s", argv[i]);
|
||||
}
|
||||
@ -1230,6 +1713,26 @@ int main(int argc, char **argv){
|
||||
*/
|
||||
if( !verboseFlag && !quietFlag ) printf("%s:", zDbName);
|
||||
for(pSql=g.pFirstSql; pSql; pSql=pSql->pNext){
|
||||
if( isDbSql(pSql->a, pSql->sz) ){
|
||||
sqlite3_snprintf(sizeof(g.zTestName), g.zTestName, "sqlid=%d",pSql->id);
|
||||
if( verboseFlag ){
|
||||
printf("%s\n", g.zTestName);
|
||||
fflush(stdout);
|
||||
}else if( !quietFlag ){
|
||||
static int prevAmt = -1;
|
||||
int idx = pSql->seq;
|
||||
int amt = idx*10/(g.nSql);
|
||||
if( amt!=prevAmt ){
|
||||
printf(" %d%%", amt*10);
|
||||
fflush(stdout);
|
||||
prevAmt = amt;
|
||||
}
|
||||
}
|
||||
runCombinedDbSqlInput(pSql->a, pSql->sz);
|
||||
nTest++;
|
||||
g.zTestName[0] = 0;
|
||||
continue;
|
||||
}
|
||||
for(pDb=g.pFirstDb; pDb; pDb=pDb->pNext){
|
||||
int openFlags;
|
||||
const char *zVfs = "inmem";
|
||||
|
BIN
test/fuzzdata8.db
Normal file
BIN
test/fuzzdata8.db
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user