1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-08 03:22:21 +03:00

Add further test cases and minor fixes for the fuzzer.

FossilOrigin-Name: 583dde93a9176ba4fff85241bafbbe4e5a6cc95f
This commit is contained in:
dan
2012-02-21 10:36:27 +00:00
parent 5577671da3
commit 766348febe
4 changed files with 272 additions and 35 deletions

View File

@@ -1,5 +1,5 @@
C Updates\sto\sthe\sinstructions\sin\sthe\sheader\scomment\sof\sthe\sfuzzer\simplementation.\nNew\stest\scases\sfor\sthe\sfuzzer. C Add\sfurther\stest\scases\sand\sminor\sfixes\sfor\sthe\sfuzzer.
D 2012-02-20T22:44:12.628 D 2012-02-21T10:36:27.146
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 3f79a373e57c3b92dabf76f40b065e719d31ac34 F Makefile.in 3f79a373e57c3b92dabf76f40b065e719d31ac34
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -206,7 +206,7 @@ F src/test_config.c a036a69b550ebc477ab9ca2b37269201f888436e
F src/test_demovfs.c 20a4975127993f4959890016ae9ce5535a880094 F src/test_demovfs.c 20a4975127993f4959890016ae9ce5535a880094
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
F src/test_func.c 6232d722a4ddb193035aa13a03796bf57d6c12fd F src/test_func.c 6232d722a4ddb193035aa13a03796bf57d6c12fd
F src/test_fuzzer.c 2c0d96f94fdf7bfc2458dac9835c87b2086fdb67 F src/test_fuzzer.c d557ab99e9f1c0d8ae7ac639b4c3d4babd279f90
F src/test_hexio.c c4773049603151704a6ab25ac5e936b5109caf5a F src/test_hexio.c c4773049603151704a6ab25ac5e936b5109caf5a
F src/test_init.c 3cbad7ce525aec925f8fda2192d576d47f0d478a F src/test_init.c 3cbad7ce525aec925f8fda2192d576d47f0d478a
F src/test_intarray.c d879bbf8e4ce085ab966d1f3c896a7c8b4f5fc99 F src/test_intarray.c d879bbf8e4ce085ab966d1f3c896a7c8b4f5fc99
@@ -504,7 +504,7 @@ F test/fuzz2.test 207d0f9d06db3eaf47a6b7bfc835b8e2fc397167
F test/fuzz3.test aec64345184d1662bd30e6a17851ff659d596dc5 F test/fuzz3.test aec64345184d1662bd30e6a17851ff659d596dc5
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26 F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26
F test/fuzzer1.test 830e260b10213d5dc6aadccc1fc4b0c7fefce7b8 F test/fuzzer1.test 098fc6dc6edcc8430d8e29a27eae6b9825d35470
F test/hook.test 5f3749de6462a6b87b4209b74adf7df5ac2df639 F test/hook.test 5f3749de6462a6b87b4209b74adf7df5ac2df639
F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4 F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4
F test/in.test a7b8a0f43da81cd08645b7a710099ffe9ad1126b F test/in.test a7b8a0f43da81cd08645b7a710099ffe9ad1126b
@@ -989,7 +989,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
P 90b7b957f8933047fd2878048dfa3ec4891988b8 P bf1dc7907cf1a5c7e19b04fa1278b2089316c30a
R e208940f645a7d6e8e24937143961be4 R e5d50c19b0286a351f7b9b6f103c6c32
U drh U dan
Z c02d350749266fd28db3de432a6902e8 Z 5de28f986fce8d4352f35f6c3b70b1eb

View File

@@ -1 +1 @@
bf1dc7907cf1a5c7e19b04fa1278b2089316c30a 583dde93a9176ba4fff85241bafbbe4e5a6cc95f

View File

@@ -141,6 +141,12 @@
** of the strings in the second or third column of the fuzzer data table ** of the strings in the second or third column of the fuzzer data table
** is 50 bytes. The maximum cost on a rule is 1000. ** is 50 bytes. The maximum cost on a rule is 1000.
*/ */
/* If SQLITE_DEBUG is not defined, disable assert statements. */
#ifndef SQLITE_DEBUG
# define NDEBUG
#endif
#include "sqlite3.h" #include "sqlite3.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@@ -289,7 +295,7 @@ static int fuzzerLoadOneRule(
fuzzer_rule **ppRule, /* OUT: New rule object */ fuzzer_rule **ppRule, /* OUT: New rule object */
char **pzErr /* OUT: Error message */ char **pzErr /* OUT: Error message */
){ ){
int iRuleset = sqlite3_column_int(pStmt, 0); sqlite3_int64 iRuleset = sqlite3_column_int64(pStmt, 0);
const char *zFrom = (const char *)sqlite3_column_text(pStmt, 1); const char *zFrom = (const char *)sqlite3_column_text(pStmt, 1);
const char *zTo = (const char *)sqlite3_column_text(pStmt, 2); const char *zTo = (const char *)sqlite3_column_text(pStmt, 2);
int nCost = sqlite3_column_int(pStmt, 3); int nCost = sqlite3_column_int(pStmt, 3);
@@ -311,16 +317,21 @@ static int fuzzerLoadOneRule(
} }
if( nCost<=0 || nCost>FUZZER_MX_COST ){ if( nCost<=0 || nCost>FUZZER_MX_COST ){
*pzErr = sqlite3_mprintf("cost must be between 1 and %d", FUZZER_MX_COST); *pzErr = sqlite3_mprintf("%s: cost must be between 1 and %d",
p->zClassName, FUZZER_MX_COST
);
rc = SQLITE_ERROR; rc = SQLITE_ERROR;
}else }else
if( nFrom>FUZZER_MX_LENGTH || nTo>FUZZER_MX_LENGTH ){ if( nFrom>FUZZER_MX_LENGTH || nTo>FUZZER_MX_LENGTH ){
*pzErr = sqlite3_mprintf("maximum string length is %d", FUZZER_MX_LENGTH); *pzErr = sqlite3_mprintf("%s: maximum string length is %d",
p->zClassName, FUZZER_MX_LENGTH
);
rc = SQLITE_ERROR; rc = SQLITE_ERROR;
}else }else
if( iRuleset<0 || iRuleset>FUZZER_MX_RULEID ){ if( iRuleset<0 || iRuleset>FUZZER_MX_RULEID ){
*pzErr = sqlite3_mprintf( *pzErr = sqlite3_mprintf("%s: ruleset must be between 0 and %d",
"ruleset must be between 0 and %d", FUZZER_MX_RULEID); p->zClassName, FUZZER_MX_RULEID
);
rc = SQLITE_ERROR; rc = SQLITE_ERROR;
}else{ }else{
@@ -335,7 +346,7 @@ static int fuzzerLoadOneRule(
memcpy(pRule->zTo, zTo, nTo+1); memcpy(pRule->zTo, zTo, nTo+1);
pRule->nTo = nTo; pRule->nTo = nTo;
pRule->rCost = nCost; pRule->rCost = nCost;
pRule->iRuleset = iRuleset; pRule->iRuleset = (int)iRuleset;
} }
} }
@@ -419,6 +430,59 @@ static int fuzzerLoadRules(
return rc; return rc;
} }
/*
** This function converts an SQL quoted string into an unquoted string
** and returns a pointer to a buffer allocated using sqlite3_malloc()
** containing the result. The caller should eventually free this buffer
** using sqlite3_free.
**
** Examples:
**
** "abc" becomes abc
** 'xyz' becomes xyz
** [pqr] becomes pqr
** `mno` becomes mno
*/
static char *fuzzerDequote(const char *zIn){
int nIn; /* Size of input string, in bytes */
char *zOut; /* Output (dequoted) string */
nIn = strlen(zIn);
zOut = sqlite3_malloc(nIn+1);
if( zOut ){
char q = zIn[0]; /* Quote character (if any ) */
if( q!='[' && q!= '\'' && q!='"' && q!='`' ){
memcpy(zOut, zIn, nIn+1);
}else{
int iOut = 0; /* Index of next byte to write to output */
int iIn; /* Index of next byte to read from input */
if( q=='[' ) q = ']';
for(iIn=1; iIn<nIn; iIn++){
if( zIn[iIn]==q ) iIn++;
zOut[iOut++] = zIn[iIn];
}
}
assert( strlen(zOut)<=nIn );
}
return zOut;
}
/*
** xDisconnect/xDestroy method for the fuzzer module.
*/
static int fuzzerDisconnect(sqlite3_vtab *pVtab){
fuzzer_vtab *p = (fuzzer_vtab*)pVtab;
assert( p->nCursor==0 );
while( p->pRule ){
fuzzer_rule *pRule = p->pRule;
p->pRule = pRule->pNext;
sqlite3_free(pRule);
}
sqlite3_free(p);
return SQLITE_OK;
}
/* /*
** xConnect/xCreate method for the fuzzer module. Arguments are: ** xConnect/xCreate method for the fuzzer module. Arguments are:
@@ -453,15 +517,24 @@ static int fuzzerConnect(
if( pNew==0 ){ if( pNew==0 ){
rc = SQLITE_NOMEM; rc = SQLITE_NOMEM;
}else{ }else{
char *zTab; /* Dequoted name of fuzzer data table */
memset(pNew, 0, sizeof(*pNew)); memset(pNew, 0, sizeof(*pNew));
pNew->zClassName = (char*)&pNew[1]; pNew->zClassName = (char*)&pNew[1];
memcpy(pNew->zClassName, zModule, nModule+1); memcpy(pNew->zClassName, zModule, nModule+1);
rc = fuzzerLoadRules(db, pNew, zDb, argv[3], pzErr); zTab = fuzzerDequote(argv[3]);
if( rc==SQLITE_OK ){ if( zTab==0 ){
sqlite3_declare_vtab(db, "CREATE TABLE x(word, distance,ruleset)"); rc = SQLITE_NOMEM;
}else{ }else{
sqlite3_free(pNew); rc = fuzzerLoadRules(db, pNew, zDb, zTab, pzErr);
sqlite3_free(zTab);
}
if( rc==SQLITE_OK ){
sqlite3_declare_vtab(db, "CREATE TABLE x(word, distance, ruleset)");
}else{
fuzzerDisconnect((sqlite3_vtab *)pNew);
pNew = 0; pNew = 0;
} }
} }
@@ -470,22 +543,6 @@ static int fuzzerConnect(
*ppVtab = (sqlite3_vtab *)pNew; *ppVtab = (sqlite3_vtab *)pNew;
return rc; return rc;
} }
/* Note that for this virtual table, the xCreate and xConnect
** methods are identical. */
static int fuzzerDisconnect(sqlite3_vtab *pVtab){
fuzzer_vtab *p = (fuzzer_vtab*)pVtab;
assert( p->nCursor==0 );
while( p->pRule ){
fuzzer_rule *pRule = p->pRule;
p->pRule = pRule->pNext;
sqlite3_free(pRule);
}
sqlite3_free(p);
return SQLITE_OK;
}
/* The xDisconnect and xDestroy methods are also the same */
/* /*
** Open a new fuzzer cursor. ** Open a new fuzzer cursor.

View File

@@ -22,6 +22,8 @@ ifcapable !vtab {
return return
} }
set ::testprefix fuzzer1
register_fuzzer_module db register_fuzzer_module db
@@ -1538,4 +1540,182 @@ do_execsql_test fuzzer1-4.1 {
SELECT word FROM f3 WHERE word MATCH 'ax' SELECT word FROM f3 WHERE word MATCH 'ax'
} {ax ay} } {ax ay}
#-------------------------------------------------------------------------
#
# 1.5.1 - Check things work with a fuzzer data table name that requires
# quoting. Also that NULL entries in the "from" column of the
# data table are treated as zero length strings ('').
#
# 1.5.2 - Check that no-op rules (i.e. C->C) are ignored. Test NULL in
# the "to" column of a fuzzer data table.
#
# 1.5.3 - Test out-of-range values for the cost field of the data table.
#
# 1.5.4 - Test out-of-range values for the string fields of the data table.
#
# 1.5.5 - Test out-of-range values for the ruleset field of the data table.
#
do_execsql_test 5.1 {
CREATE TABLE "fuzzer [x] rules table"(a, b, c, d);
INSERT INTO "fuzzer [x] rules table" VALUES(0, NULL, 'abc', 10);
CREATE VIRTUAL TABLE x USING fuzzer('fuzzer [x] rules table');
SELECT word, distance FROM x WHERE word MATCH '123' LIMIT 4;
} {123 0 abc123 10 1abc23 10 12abc3 10}
do_execsql_test 5.2 {
DELETE FROM "fuzzer [x] rules table";
INSERT INTO "fuzzer [x] rules table" VALUES(0, 'x', NULL, 20);
INSERT INTO "fuzzer [x] rules table" VALUES(0, NULL, NULL, 10);
INSERT INTO "fuzzer [x] rules table" VALUES(0, 'x', 'x', 10);
DROP TABLE x;
CREATE VIRTUAL TABLE x USING fuzzer('fuzzer [x] rules table');
SELECT word, distance FROM x WHERE word MATCH 'xx';
} {xx 0 x 20 {} 40}
do_execsql_test 5.3.1 {
DROP TABLE IF EXISTS x;
INSERT INTO "fuzzer [x] rules table" VALUES(0, 'c', 'd', 1001);
}
do_catchsql_test 5.3.2 {
CREATE VIRTUAL TABLE x USING fuzzer('fuzzer [x] rules table');
} {1 {fuzzer: cost must be between 1 and 1000}}
do_execsql_test 5.3.3 {
DROP TABLE IF EXISTS x;
DELETE FROM "fuzzer [x] rules table";
INSERT INTO "fuzzer [x] rules table" VALUES(0, 'd', 'c', 0);
}
do_catchsql_test 5.3.4 {
CREATE VIRTUAL TABLE x USING fuzzer('fuzzer [x] rules table');
} {1 {fuzzer: cost must be between 1 and 1000}}
do_execsql_test 5.3.5 {
DROP TABLE IF EXISTS x;
DELETE FROM "fuzzer [x] rules table";
INSERT INTO "fuzzer [x] rules table" VALUES(0, 'd', 'c', -20);
}
do_catchsql_test 5.3.6 {
CREATE VIRTUAL TABLE x USING fuzzer('fuzzer [x] rules table');
} {1 {fuzzer: cost must be between 1 and 1000}}
do_execsql_test 5.4.1 {
DROP TABLE IF EXISTS x;
DELETE FROM "fuzzer [x] rules table";
INSERT INTO "fuzzer [x] rules table" VALUES(
0, 'x', '12345678901234567890123456789012345678901234567890', 2
);
CREATE VIRTUAL TABLE x USING fuzzer('fuzzer [x] rules table');
SELECT word FROM x WHERE word MATCH 'x';
} {x 12345678901234567890123456789012345678901234567890}
do_execsql_test 5.4.2 {
DROP TABLE IF EXISTS x;
DELETE FROM "fuzzer [x] rules table";
INSERT INTO "fuzzer [x] rules table" VALUES(
0, 'x', '123456789012345678901234567890123456789012345678901', 2
);
}
do_catchsql_test 5.4.3 {
CREATE VIRTUAL TABLE x USING fuzzer('fuzzer [x] rules table');
} {1 {fuzzer: maximum string length is 50}}
do_execsql_test 5.4.4 {
DROP TABLE IF EXISTS x;
DELETE FROM "fuzzer [x] rules table";
INSERT INTO "fuzzer [x] rules table" VALUES(
0, '123456789012345678901234567890123456789012345678901', 'x', 2
);
}
do_catchsql_test 5.4.5 {
CREATE VIRTUAL TABLE x USING fuzzer('fuzzer [x] rules table');
} {1 {fuzzer: maximum string length is 50}}
do_execsql_test 5.5.1 {
DROP TABLE IF EXISTS x;
DELETE FROM "fuzzer [x] rules table";
INSERT INTO "fuzzer [x] rules table" VALUES(-1, 'x', 'y', 2);
}
do_catchsql_test 5.5.2 {
CREATE VIRTUAL TABLE x USING fuzzer('fuzzer [x] rules table');
} {1 {fuzzer: ruleset must be between 0 and 2147483647}}
do_execsql_test 5.5.3 {
DROP TABLE IF EXISTS x;
DELETE FROM "fuzzer [x] rules table";
INSERT INTO "fuzzer [x] rules table" VALUES((1<<32)+100, 'x', 'y', 2);
}
do_catchsql_test 5.5.4 {
CREATE VIRTUAL TABLE x USING fuzzer('fuzzer [x] rules table');
} {1 {fuzzer: ruleset must be between 0 and 2147483647}}
#-------------------------------------------------------------------------
# This test uses a fuzzer table with many rules. There is one rule to
# map each possible two character string, where characters are lower-case
# letters used in the English language, to all other possible two character
# strings. In total, (26^4)-(26^2) mappings (the subtracted term represents
# the no-op mappings discarded automatically by the fuzzer).
#
#
do_execsql_test 6.1.1 {
DROP TABLE IF EXISTS x1;
DROP TABLE IF EXISTS x1_rules;
CREATE TABLE x1_rules(ruleset, cFrom, cTo, cost);
}
puts "This test is slow - perhaps around 7 seconds on an average pc"
do_test 6.1.2 {
set LETTERS {a b c d e f g h i j k l m n o p q r s t u v w x y z}
set cost 1
db transaction {
foreach c1 $LETTERS {
foreach c2 $LETTERS {
foreach c3 $LETTERS {
foreach c4 $LETTERS {
db eval {INSERT INTO x1_rules VALUES(0, $c1||$c2, $c3||$c4, $cost)}
set cost [expr ($cost%1000) + 1]
}
}
}
}
db eval {UPDATE x1_rules SET cost = 20 WHERE cost<20 AND cFrom!='xx'}
}
} {}
do_execsql_test 6.2 {
SELECT count(*) FROM x1_rules WHERE cTo!=cFrom;
} [expr 26*26*26*26 - 26*26]
do_execsql_test 6.2.1 {
CREATE VIRTUAL TABLE x1 USING fuzzer(x1_rules);
SELECT word FROM x1 WHERE word MATCH 'xx' LIMIT 10;
} {xx hw hx hy hz ia ib ic id ie}
do_execsql_test 6.2.2 {
SELECT cTo FROM x1_rules WHERE cFrom='xx'
ORDER BY cost asc, rowid asc LIMIT 9;
} {hw hx hy hz ia ib ic id ie}
#-------------------------------------------------------------------------
# Test using different types of quotes with CREATE VIRTUAL TABLE
# arguments.
#
do_execsql_test 7.1 {
CREATE TABLE [x2 "rules] (a, b, c, d);
INSERT INTO [x2 "rules] VALUES(0, 'a', 'b', 5);
}
foreach {tn sql} {
1 { CREATE VIRTUAL TABLE x2 USING fuzzer( [x2 "rules] ) }
2 { CREATE VIRTUAL TABLE x2 USING fuzzer( "x2 ""rules" ) }
3 { CREATE VIRTUAL TABLE x2 USING fuzzer( 'x2 "rules' ) }
4 { CREATE VIRTUAL TABLE x2 USING fuzzer( `x2 "rules` ) }
} {
do_execsql_test 7.2.$tn.1 { DROP TABLE IF EXISTS x2 }
do_execsql_test 7.2.$tn.2 $sql
do_execsql_test 7.2.$tn.3 {
SELECT word FROM x2 WHERE word MATCH 'aaa'
} {aaa baa aba aab bab abb bba bbb}
}
finish_test finish_test