From 53e66c3cda52c5bda5d917ecf7b4bed2c3dfa926 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 24 Jul 2015 15:49:23 +0000 Subject: [PATCH] More robust handling of zeroblob() with oversized arguments. Fix fuzzcheck so that it can be run with limited heap memory. FossilOrigin-Name: 4e3e516a42059c97f42a7eb59bdf5cded0ff843a --- Makefile.in | 4 +-- Makefile.msc | 2 +- main.mk | 9 +++--- manifest | 28 ++++++++-------- manifest.uuid | 2 +- src/func.c | 1 + src/vdbe.c | 2 +- src/vdbeapi.c | 2 +- test/fuzzcheck.c | 81 ++++++++++++++++++++++++++++++++++++++++++++-- test/zeroblob.test | 2 +- 10 files changed, 105 insertions(+), 28 deletions(-) diff --git a/Makefile.in b/Makefile.in index 9886377a4b..4a03129d08 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1044,10 +1044,10 @@ fulltestonly: $(TESTPROGS) # Fuzz testing fuzztest: fuzzcheck$(TEXE) $(FUZZDATA) - ./fuzzcheck$(TEXE) $(FUZZDATA) + ./fuzzcheck$(TEXE) --limit-mem 100M $(FUZZDATA) valgrindfuzz: fuzzcheck$(TEXT) $(FUZZDATA) - valgrind ./fuzzcheck$(TEXE) --cell-size-check --quiet $(FUZZDATA) + valgrind ./fuzzcheck$(TEXE) --cell-size-check --limit-mem 100M $(FUZZDATA) # Minimal testing that runs in less than 3 minutes # diff --git a/Makefile.msc b/Makefile.msc index bec86b1bc9..1f2c0299bc 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -1736,7 +1736,7 @@ queryplantest: testfixture.exe sqlite3.exe .\testfixture.exe $(TOP)\test\permutations.test queryplanner $(TESTOPTS) fuzztest: fuzzcheck.exe - .\fuzzcheck.exe $(FUZZDATA) + .\fuzzcheck.exe --limit-mem 100M $(FUZZDATA) # Minimal testing that runs in less than 3 minutes (on a fast machine) # diff --git a/main.mk b/main.mk index c1a0e73d40..9ec193e73d 100644 --- a/main.mk +++ b/main.mk @@ -446,11 +446,12 @@ sqldiff$(EXE): $(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h $(TOP)/tool/sqldiff.c sqlite3.c $(TLIBS) $(THREADLIB) fuzzershell$(EXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h - $(TCCX) -o fuzzershell$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION\ + $(TCCX) -o fuzzershell$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \ $(TOP)/tool/fuzzershell.c sqlite3.c $(TLIBS) $(THREADLIB) fuzzcheck$(EXE): $(TOP)/test/fuzzcheck.c sqlite3.c sqlite3.h - $(TCCX) -o fuzzcheck$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION\ + $(TCCX) -o fuzzcheck$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \ + -DSQLITE_ENABLE_MEMSYS5 \ $(TOP)/test/fuzzcheck.c sqlite3.c $(TLIBS) $(THREADLIB) mptester$(EXE): sqlite3.c $(TOP)/mptest/mptest.c @@ -722,10 +723,10 @@ queryplantest: testfixture$(EXE) sqlite3$(EXE) ./testfixture$(EXE) $(TOP)/test/permutations.test queryplanner $(TESTOPTS) fuzztest: fuzzcheck$(EXE) $(FUZZDATA) - ./fuzzcheck$(EXE) $(FUZZDATA) + ./fuzzcheck$(EXE) --limit-mem 100M $(FUZZDATA) valgrindfuzz: fuzzcheck$(EXE) $(FUZZDATA) - valgrind ./fuzzcheck$(EXE) --cell-size-check --quiet $(FUZZDATA) + valgrind ./fuzzcheck$(EXE) --cell-size-check --limit-mem 100M $(FUZZDATA) # A very quick test using only testfixture and omitting all the slower # tests. Designed to run in under 3 minutes on a workstation. diff --git a/manifest b/manifest index 240c60a50c..7e72c765a9 100644 --- a/manifest +++ b/manifest @@ -1,9 +1,9 @@ -C Modify\sa\sfew\stest\sscripts\sto\savoid\sleaving\sthe\ssqlite3Config\sstructure\sin\sa\snon-default\sstate. -D 2015-07-24T14:17:17.027 +C More\srobust\shandling\sof\szeroblob()\swith\soversized\sarguments.\s\sFix\sfuzzcheck\nso\sthat\sit\scan\sbe\srun\swith\slimited\sheap\smemory. +D 2015-07-24T15:49:23.313 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f -F Makefile.in b13c653ee215cb0d294ffa4f10ac4d14255767e0 +F Makefile.in 6a2355cacb04337e6f29a95200512b1cdd8c1857 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 -F Makefile.msc cddf142cac25c011aadd69a371399db9a8892ccd +F Makefile.msc ae4aebdc5581367a3c4b107f395b8a39cae69f0c F Makefile.vxworks e1b65dea203f054e71653415bd8f96dcaed47858 F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F VERSION ce0ae95abd7121c534f6917c1c8f2b70d9acd4db @@ -248,7 +248,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk 4affd40e93db8e0063c2a0768c1887b3e2a272a1 +F main.mk c94f70684cebc5108c73d5ac3af10297f296f373 F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea F mkopcodeh.awk 0e7f04a8eb90f92259e47d80110e4e98d7ce337a F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 @@ -282,7 +282,7 @@ F src/delete.c 8857a6f27560718f65d43bdbec86c967ae1f8dfa F src/expr.c c5c58e4d01c7ceb2266791d8d877f1b23a88e316 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c c9b63a217d86582c22121699a47f22f524608869 -F src/func.c a98ea5880dc50e9ca6dd6f57079a37b9cfcdecf1 +F src/func.c d08d2106ba10dddbee45e001b8516f4d1df2b20e F src/global.c 508e4087f7b41d688e4762dcf4d4fe28cfbc87f9 F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5 F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094 @@ -390,10 +390,10 @@ F src/update.c 487747b328b7216bb7f6af0695d6937d5c9e605f F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c F src/util.c 46358a204b35971a839341cf64599d65b151ba88 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701 -F src/vdbe.c 5ee4a2bf871418f61d06dc256b9b3a0084b5ec46 +F src/vdbe.c 86be40a4568f5385048ea6623adfd11ddb7bf710 F src/vdbe.h 7a75045d879118b9d3af7e8b3c108f2f27c51473 F src/vdbeInt.h 8b54e01ad0463590e7cffabce0bc36da9ee4f816 -F src/vdbeapi.c 2fa7ed7520313d6dd1dc6e6495999201c630adfc +F src/vdbeapi.c 082746d4c4788d889a2a62b858d753453e9c9c6d F src/vdbeaux.c 787f5f9d58f4c6f39294ed06909ba602d1a402e6 F src/vdbeblob.c 4f2e8e075d238392df98c5e03a64342465b03f90 F src/vdbemem.c ae38a0d35ae71cf604381a887c170466ba518090 @@ -735,7 +735,7 @@ F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1 F test/fuzz3.test 53fabcd5f0f430f8b221282f6c12c4d0903c21eb F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26 -F test/fuzzcheck.c b973b06b500e6fc052d7059257cdf70df1f3a986 +F test/fuzzcheck.c 79980bbc00e19ad44c3ba6699e643348572757a2 F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664 F test/fuzzdata2.db f03a420d3b822cc82e4f894ca957618fbe9c4973 F test/fuzzdata3.db 1d6044c33a114007f02b6e6846f1fa232f607bfd @@ -1307,7 +1307,7 @@ F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a F test/without_rowid5.test 61256715b686359df48ca1742db50cc7e3e7b862 F test/without_rowid6.test db0dbf03c49030aa3c1ba5f618620334bd2baf5f F test/wordcount.c 9915e06cb33d8ca8109b8700791afe80d305afda -F test/zeroblob.test dcffae9583ac7a6683e814cc7a9c85b2fd73ddd8 +F test/zeroblob.test 202dbc81129a4a1509f829384b2b8aaf091635a9 F test/zerodamage.test cf6748bad89553cc1632be51a6f54e487e4039ac F tool/build-all-msvc.bat 9058bd90a3c078a3d8c17d40e853aaa0f47885f4 x F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367 @@ -1365,7 +1365,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 119883a21bdcab66c15d1e80f3da20addda328ad -R f93dc01dd263cc307f98235646fce28d -U dan -Z 1717e31dfb28e99256b065adb47b07f0 +P 562687d9f56bf4bb0f5f07f97cbbb7649c81faf8 +R 1786aea7f8e6749074e67e1af5c8c763 +U drh +Z 01a0292cb698589e36de0afbd61cb525 diff --git a/manifest.uuid b/manifest.uuid index 77a88cee90..701da3a27b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -562687d9f56bf4bb0f5f07f97cbbb7649c81faf8 \ No newline at end of file +4e3e516a42059c97f42a7eb59bdf5cded0ff843a \ No newline at end of file diff --git a/src/func.c b/src/func.c index d0565357d5..151a09f299 100644 --- a/src/func.c +++ b/src/func.c @@ -1131,6 +1131,7 @@ static void zeroblobFunc( if( n>db->aLimit[SQLITE_LIMIT_LENGTH] ){ sqlite3_result_error_toobig(context); }else{ + if( n<0 ) n = 0; sqlite3_result_zeroblob(context, (int)n); /* IMP: R-00293-64994 */ } } diff --git a/src/vdbe.c b/src/vdbe.c index 296a12bc9f..fe97087c09 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2702,7 +2702,7 @@ case OP_MakeRecord: { len = sqlite3VdbeSerialTypeLen(serial_type); if( pRec->flags & MEM_Zero ){ if( nData ){ - sqlite3VdbeMemExpandBlob(pRec); + if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem; }else{ nZero += pRec->u.nZero; len -= pRec->u.nZero; diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 4687aac510..391e3adb03 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -162,7 +162,7 @@ int sqlite3_clear_bindings(sqlite3_stmt *pStmt){ const void *sqlite3_value_blob(sqlite3_value *pVal){ Mem *p = (Mem*)pVal; if( p->flags & (MEM_Blob|MEM_Str) ){ - sqlite3VdbeMemExpandBlob(p); + if( sqlite3VdbeMemExpandBlob(p)!=SQLITE_OK ) return 0; p->flags |= MEM_Blob; return p->n ? p->z : 0; }else{ diff --git a/test/fuzzcheck.c b/test/fuzzcheck.c index d17a9a1289..c678e2af7a 100644 --- a/test/fuzzcheck.c +++ b/test/fuzzcheck.c @@ -682,6 +682,64 @@ static void rebuild_database(sqlite3 *db){ if( rc ) fatalError("cannot rebuild: %s", sqlite3_errmsg(db)); } +/* +** Return the value of a hexadecimal digit. Return -1 if the input +** is not a hex digit. +*/ +static int hexDigitValue(char c){ + if( c>='0' && c<='9' ) return c - '0'; + if( c>='a' && c<='f' ) return c - 'a' + 10; + if( c>='A' && c<='F' ) return c - 'A' + 10; + return -1; +} + +/* +** Interpret zArg as an integer value, possibly with suffixes. +*/ +static int integerValue(const char *zArg){ + sqlite3_int64 v = 0; + static const struct { char *zSuffix; int iMult; } aMult[] = { + { "KiB", 1024 }, + { "MiB", 1024*1024 }, + { "GiB", 1024*1024*1024 }, + { "KB", 1000 }, + { "MB", 1000000 }, + { "GB", 1000000000 }, + { "K", 1000 }, + { "M", 1000000 }, + { "G", 1000000000 }, + }; + int i; + int isNeg = 0; + if( zArg[0]=='-' ){ + isNeg = 1; + zArg++; + }else if( zArg[0]=='+' ){ + zArg++; + } + if( zArg[0]=='0' && zArg[1]=='x' ){ + int x; + zArg += 2; + while( (x = hexDigitValue(zArg[0]))>=0 ){ + v = (v<<4) + x; + zArg++; + } + }else{ + while( isdigit(zArg[0]) ){ + v = v*10 + zArg[0] - '0'; + zArg++; + } + } + for(i=0; i0x7fffffff ) fatalError("parameter too large - max 2147483648"); + return (int)(isNeg? -v : v); +} + /* ** Print sketchy documentation for this utility program */ @@ -696,6 +754,7 @@ static void showHelp(void){ " --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" @@ -739,6 +798,7 @@ int main(int argc, char **argv){ int cellSzCkFlag = 0; /* --cell-size-check */ int sqlFuzz = 0; /* True for SQL fuzz testing. False for DB fuzz */ int iTimeout = 120; /* Default 120-second timeout */ + int nMem = 0; /* Memory limit */ iBegin = timeOfDay(); #ifdef __unix__ @@ -756,12 +816,16 @@ int main(int argc, char **argv){ }else if( strcmp(z,"dbid")==0 ){ if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]); - onlyDbid = atoi(argv[++i]); + onlyDbid = integerValue(argv[++i]); }else if( strcmp(z,"help")==0 ){ showHelp(); return 0; }else + if( strcmp(z,"limit-mem")==0 ){ + if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]); + nMem = integerValue(argv[++i]); + }else if( strcmp(z,"limit-vdbe")==0 ){ vdbeLimitFlag = 1; }else @@ -794,11 +858,11 @@ int main(int argc, char **argv){ }else if( strcmp(z,"sqlid")==0 ){ if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]); - onlySqlid = atoi(argv[++i]); + onlySqlid = integerValue(argv[++i]); }else if( strcmp(z,"timeout")==0 ){ if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]); - iTimeout = atoi(argv[++i]); + iTimeout = integerValue(argv[++i]); }else if( strcmp(z,"timeout-test")==0 ){ timeoutTest = 1; @@ -928,6 +992,17 @@ int main(int argc, char **argv){ if( sqlite3_memory_used()>0 ){ fatalError("SQLite has memory in use before the start of testing"); } + + /* Limit available memory, if requested */ + if( nMem>0 ){ + void *pHeap; + sqlite3_shutdown(); + pHeap = malloc(nMem); + if( pHeap==0 ){ + fatalError("failed to allocate %d bytes of heap memory", nMem); + } + sqlite3_config(SQLITE_CONFIG_HEAP, pHeap, nMem, 128); + } /* Register the in-memory virtual filesystem */ diff --git a/test/zeroblob.test b/test/zeroblob.test index c40ad47524..d0196a546c 100644 --- a/test/zeroblob.test +++ b/test/zeroblob.test @@ -45,7 +45,7 @@ do_test zeroblob-1.1 { } {10} do_test zeroblob-1.1.1 { - expr {[sqlite3_memory_highwater]<$::memused+25000} + expr {[sqlite3_memory_highwater]<$::memused+35000} } {1} do_test zeroblob-1.2 { execsql { -- 2.47.2