]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Prevent the fuzzer from ever returning a string longer than 100 bytes.
authordan <dan@noemail.net>
Tue, 21 Feb 2012 18:00:20 +0000 (18:00 +0000)
committerdan <dan@noemail.net>
Tue, 21 Feb 2012 18:00:20 +0000 (18:00 +0000)
FossilOrigin-Name: 969095ca3067d60f4d3a0a4ad419541cb8b146db

manifest
manifest.uuid
src/test_fuzzer.c
test/fuzzer1.test
test/fuzzerfault.test

index 833e77ac46610dd0b50cb32611eff66cf9b98946..b23524e5b753a0d6039c030dd03a04cdb69e31c2 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Further\sfuzzer\stest\scases.\sFix\sa\scase\sin\sthe\sfuzzer\swhere\san\serror\scode\swas\sbeing\sdropped.
-D 2012-02-21T14:11:12.123
+C Prevent\sthe\sfuzzer\sfrom\sever\sreturning\sa\sstring\slonger\sthan\s100\sbytes.
+D 2012-02-21T18:00:20.124
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 3f79a373e57c3b92dabf76f40b065e719d31ac34
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -206,7 +206,7 @@ F src/test_config.c a036a69b550ebc477ab9ca2b37269201f888436e
 F src/test_demovfs.c 20a4975127993f4959890016ae9ce5535a880094
 F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
 F src/test_func.c 6232d722a4ddb193035aa13a03796bf57d6c12fd
-F src/test_fuzzer.c 5d716ce83ee678471dbf91a05c33ab05f115ed61
+F src/test_fuzzer.c e81b8984e9649499c45b080b60ebe4c1f6cff8d0
 F src/test_hexio.c c4773049603151704a6ab25ac5e936b5109caf5a
 F src/test_init.c 3cbad7ce525aec925f8fda2192d576d47f0d478a
 F src/test_intarray.c d879bbf8e4ce085ab966d1f3c896a7c8b4f5fc99
@@ -504,8 +504,8 @@ F test/fuzz2.test 207d0f9d06db3eaf47a6b7bfc835b8e2fc397167
 F test/fuzz3.test aec64345184d1662bd30e6a17851ff659d596dc5
 F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
 F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26
-F test/fuzzer1.test 8fb031a789f68c29236bf90e31919ebbf94cb730
-F test/fuzzerfault.test 00fba714b2c52603c532cbf336b4901252e0e48d
+F test/fuzzer1.test 69cf1036b92fd3b8e1fd65bef4d7ee3f085c28fb
+F test/fuzzerfault.test ff2282c81797b6a355f0748d8b54c7287c5d2b25
 F test/hook.test 5f3749de6462a6b87b4209b74adf7df5ac2df639
 F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4
 F test/in.test a7b8a0f43da81cd08645b7a710099ffe9ad1126b
@@ -990,7 +990,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
 F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a
 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
-P 583dde93a9176ba4fff85241bafbbe4e5a6cc95f
-R 5eaa36a3b096a39cabce5b0dfd058e68
+P 8b77d3953f082e6fa42e42fe903ea9eddf99dd91
+R eac7c759ba0fcf7d16f2f5a90574c01e
 U dan
-Z 4089608a3cec5128a943f2b568b6cca4
+Z 5ce06301e86d5442c836392119f93673
index 3d327dbee9c871e0e5b107482ac8836ace76af9e..13c72154f008d99ae14b3149a8c7f08e29d86125 100644 (file)
@@ -1 +1 @@
-8b77d3953f082e6fa42e42fe903ea9eddf99dd91
\ No newline at end of file
+969095ca3067d60f4d3a0a4ad419541cb8b146db
\ No newline at end of file
index c7d4cfc218a71a992e128a59b6bb7c9b6836cd20..66d0bd08d4a99d52e9461062ba4754a32836ea99 100644 (file)
@@ -180,9 +180,10 @@ typedef int fuzzer_ruleid;
 /*
 ** Limits
 */
-#define FUZZER_MX_LENGTH           50   /* Maximum length of a search string */
+#define FUZZER_MX_LENGTH           50   /* Maximum length of a rule string */
 #define FUZZER_MX_RULEID   2147483647   /* Maximum rule ID */
 #define FUZZER_MX_COST           1000   /* Maximum single-rule cost */
+#define FUZZER_MX_OUTPUT_LENGTH   100   /* Maximum length of an output string */
 
 
 /*
@@ -612,8 +613,8 @@ static int fuzzerRender(
   int *pnBuf            /* Size of the buffer */
 ){
   const fuzzer_rule *pRule = pStem->pRule;
-  int n;
-  char *z;
+  int n;                          /* Size of output term without nul-term */
+  char *z;                        /* Buffer to assemble output term in */
 
   n = pStem->nBasis + pRule->nTo - pRule->nFrom;
   if( (*pnBuf)<n+1 ){
@@ -631,6 +632,8 @@ static int fuzzerRender(
     memcpy(&z[n+pRule->nTo], &pStem->zBasis[n+pRule->nFrom], 
            pStem->nBasis-n-pRule->nFrom+1);
   }
+
+  assert( z[pStem->nBasis + pRule->nTo - pRule->nFrom]==0 );
   return SQLITE_OK;
 }
 
@@ -699,6 +702,25 @@ static int fuzzerSeen(fuzzer_cursor *pCur, fuzzer_stem *pStem){
   return pLookup!=0;
 }
 
+/*
+** If argument pRule is NULL, this function returns false.
+**
+** Otherwise, it returns true if rule pRule should be skipped. A rule 
+** should be skipped if it does not belong to rule-set iRuleset, or if
+** applying it to stem pStem would create a string longer than 
+** FUZZER_MX_OUTPUT_LENGTH bytes.
+*/
+static int fuzzerSkipRule(
+  const fuzzer_rule *pRule,       /* Determine whether or not to skip this */
+  fuzzer_stem *pStem,             /* Stem rule may be applied to */
+  int iRuleset                    /* Rule-set used by the current query */
+){
+  return pRule && (
+      (pRule->iRuleset!=iRuleset)
+   || (pStem->nBasis + pRule->nTo - pRule->nFrom)>FUZZER_MX_OUTPUT_LENGTH
+  );
+}
+
 /*
 ** Advance a fuzzer_stem to its next value.   Return 0 if there are
 ** no more values that can be generated by this fuzzer_stem.  Return
@@ -706,7 +728,6 @@ static int fuzzerSeen(fuzzer_cursor *pCur, fuzzer_stem *pStem){
 */
 static int fuzzerAdvance(fuzzer_cursor *pCur, fuzzer_stem *pStem){
   const fuzzer_rule *pRule;
-  const int iSet = pCur->iRuleset;
   while( (pRule = pStem->pRule)!=0 ){
     assert( pRule==&pCur->nullRule || pRule->iRuleset==pCur->iRuleset );
     while( pStem->n < pStem->nBasis - pRule->nFrom ){
@@ -726,7 +747,7 @@ static int fuzzerAdvance(fuzzer_cursor *pCur, fuzzer_stem *pStem){
     pStem->n = -1;
     do{
       pRule = pRule->pNext;
-    }while( pRule && pRule->iRuleset!=iSet );
+    }while( fuzzerSkipRule(pRule, pStem, pCur->iRuleset) );
     pStem->pRule = pRule;
     if( pRule && fuzzerCost(pStem)>pCur->rLimit ) pStem->pRule = 0;
   }
@@ -856,7 +877,7 @@ static fuzzer_stem *fuzzerNewStem(
   pNew->nBasis = strlen(zWord);
   memcpy(pNew->zBasis, zWord, pNew->nBasis+1);
   pRule = pCur->pVtab->pRule;
-  while( pRule && pRule->iRuleset!=pCur->iRuleset ){
+  while( fuzzerSkipRule(pRule, pNew, pCur->iRuleset) ){
     pRule = pRule->pNext;
   }
   pNew->pRule = pRule;
@@ -906,7 +927,10 @@ static int fuzzerNext(sqlite3_vtab_cursor *cur){
   ** stem list is the next lowest cost word.
   */
   while( (pStem = pCur->pStem)!=0 ){
-    if( fuzzerAdvance(pCur, pStem) ){
+    int res = fuzzerAdvance(pCur, pStem);
+    if( res<0 ){
+      return SQLITE_NOMEM;
+    }else if( res>0 ){
       pCur->pStem = 0;
       pStem = fuzzerInsert(pCur, pStem);
       if( (rc = fuzzerSeen(pCur, pStem))!=0 ){
@@ -944,7 +968,7 @@ static int fuzzerFilter(
   int argc, sqlite3_value **argv
 ){
   fuzzer_cursor *pCur = (fuzzer_cursor *)pVtabCursor;
-  const char *zWord = 0;
+  const char *zWord = "";
   fuzzer_stem *pStem;
   int idx;
 
@@ -963,17 +987,25 @@ static int fuzzerFilter(
     pCur->iRuleset = (fuzzer_cost)sqlite3_value_int(argv[idx]);
     idx++;
   }
-  if( zWord==0 ) zWord = "";
-  pCur->pStem = pStem = fuzzerNewStem(pCur, zWord, (fuzzer_cost)0);
-  if( pStem==0 ) return SQLITE_NOMEM;
   pCur->nullRule.pNext = pCur->pVtab->pRule;
   pCur->nullRule.rCost = 0;
   pCur->nullRule.nFrom = 0;
   pCur->nullRule.nTo = 0;
   pCur->nullRule.zFrom = "";
-  pStem->pRule = &pCur->nullRule;
-  pStem->n = pStem->nBasis;
   pCur->iRowid = 1;
+  assert( pCur->pStem==0 );
+
+  /* If the query term is longer than FUZZER_MX_OUTPUT_LENGTH bytes, this
+  ** query will return zero rows.  */
+  if( strlen(zWord)<FUZZER_MX_OUTPUT_LENGTH ){
+    pCur->pStem = pStem = fuzzerNewStem(pCur, zWord, (fuzzer_cost)0);
+    if( pStem==0 ) return SQLITE_NOMEM;
+    pStem->pRule = &pCur->nullRule;
+    pStem->n = pStem->nBasis;
+  }else{
+    pCur->rLimit = 0;
+  }
+
   return SQLITE_OK;
 }
 
@@ -1156,7 +1188,7 @@ static int register_fuzzer_module(
     Tcl_WrongNumArgs(interp, 1, objv, "DB");
     return TCL_ERROR;
   }
-  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
+  getDbPointer(interp, Tcl_GetString(objv[1]), &db);
   fuzzer_register(db);
   return TCL_OK;
 }
index 97209c32732bbacb21b9afaca41b75e9caf8674a..dc8b445ee9e4eb33392aaa195cb198c1e053130b 100644 (file)
@@ -24,9 +24,12 @@ ifcapable !vtab {
 
 set ::testprefix fuzzer1
 
-register_fuzzer_module db
-
+# Test of test code. Only here to make the coverage metric better.
+do_test 0.1 {
+  list [catch { register_fuzzer_module a b c } msg] $msg
+} {1 {wrong # args: should be "register_fuzzer_module DB"}}
 
+register_fuzzer_module db
 
 # Check configuration errors.
 #
@@ -1824,6 +1827,42 @@ do_execsql_test 8.2.14 {
   SELECT word FROM x3 WHERE ruleset=1 AND word MATCH 'a' ORDER BY word DESC;
 } {v u t a}
 
+#-------------------------------------------------------------------------
+#
+do_execsql_test 9.1 {
+  CREATE TABLE x4_rules(a, b, c, d);
+  INSERT INTO x4_rules VALUES(0, 'a', 'b', 10);
+  INSERT INTO x4_rules VALUES(0, 'a', 'c', 11);
+  INSERT INTO x4_rules VALUES(0, 'bx', 'zz', 20);
+  INSERT INTO x4_rules VALUES(0, 'cx', 'yy', 15);
+  INSERT INTO x4_rules VALUES(0, 'zz', '!!', 50);
+  CREATE VIRTUAL TABLE x4 USING fuzzer(x4_rules);
+}
+
+do_execsql_test 9.2 {
+  SELECT word, distance FROM x4 WHERE word MATCH 'ax';
+} {ax 0 bx 10 cx 11 yy 26 zz 30 !! 80}
+
+
+do_execsql_test 10.1 {
+  CREATE TABLE x5_rules(a, b, c, d);
+  CREATE VIRTUAL TABLE x5 USING fuzzer(x5_rules);
+}
+
+do_execsql_test 10.2 {
+  SELECT word, distance FROM x5 WHERE word MATCH 
+    'aaaaaaaaaXaaaaaaaaaXaaaaaaaaaXaaaaaaaaaXaaaaaaaaa' || 
+    'aaaaaaaaaXaaaaaaaaaXaaaaaaaaaXaaaaaaaaaXaaaaaaaaa' || 
+    'aaaaaaaaaXaaaaaaaaaXaaaaaaaaaXaaaaaaaaaXaaaaaaaaa'
+} {}
+
+do_execsql_test 10.3 {
+  INSERT INTO x5_rules VALUES(0, 'a', '0.1.2.3.4.5.6.7.8.9.a', 1);
+  DROP TABLE x5;
+  CREATE VIRTUAL TABLE x5 USING fuzzer(x5_rules);
+  SELECT length(word) FROM x5 WHERE word MATCH 'a' LIMIT 50;
+} {1 21 41 61 81}
 
 finish_test
 
+
index 7ef26af1f6e164ffca450b790748c081ad40f418..067da7f5fcf10a9f0fb13bb18f25ca9178b4bf8f 100644 (file)
@@ -28,8 +28,7 @@ do_test 1-pre1 {
   }
   faultsim_save_and_close
 } {}
-
-do_faultsim_test 1 -faults oom-t* -prep {
+do_faultsim_test 1 -prep {
   faultsim_restore_and_reopen
   register_fuzzer_module db
 } -body {
@@ -42,6 +41,52 @@ do_faultsim_test 1 -faults oom-t* -prep {
                        {1 {vtable constructor failed: x1}}
 }
 
+do_test 2-pre1 {
+  faultsim_delete_and_reopen
+  register_fuzzer_module db
+  execsql {
+    CREATE TABLE x2_rules(ruleset, cFrom, cTo, cost);
+    INSERT INTO x2_rules VALUES(0, 'a', 'x', 1);
+    INSERT INTO x2_rules VALUES(0, 'b', 'x', 2);
+    INSERT INTO x2_rules VALUES(0, 'c', 'x', 3);
+    CREATE VIRTUAL TABLE x2 USING fuzzer(x2_rules);
+  }
+  faultsim_save_and_close
+} {}
+
+do_faultsim_test 2 -prep {
+  faultsim_restore_and_reopen
+  register_fuzzer_module db
+} -body {
+  execsql { 
+    SELECT count(*) FROM x2 WHERE word MATCH 'abc';
+  }
+} -test {
+  faultsim_test_result {0 8} {1 {vtable constructor failed: x2}}
+}
+
+do_test 3-pre1 {
+  faultsim_delete_and_reopen
+  execsql {
+    CREATE TABLE x1_rules(ruleset, cFrom, cTo, cost);
+    INSERT INTO x1_rules VALUES(0, 'a', 
+      '123456789012345678901234567890a1234567890123456789', 10
+    );
+  }
+  faultsim_save_and_close
+} {}
+
+do_faultsim_test 3 -prep {
+  faultsim_restore_and_reopen
+  register_fuzzer_module db
+} -body {
+  execsql { 
+    CREATE VIRTUAL TABLE x1 USING fuzzer(x1_rules);
+    SELECT count(*) FROM (SELECT * FROM x1 WHERE word MATCH 'a' LIMIT 2);
+  }
+} -test {
+  faultsim_test_result {0 2} {1 {vtable constructor failed: x1}}
+}
 
 
 finish_test