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

Further improvements to the fuzzer. It still is not quite working. Pausing

to work on other things....

FossilOrigin-Name: 5f2f2fce40f43debeb0492c9b460b85c7dad2bde
This commit is contained in:
drh
2011-03-29 14:08:09 +00:00
parent 94169564fa
commit 72384dc28f
7 changed files with 114 additions and 75 deletions

View File

@@ -17,6 +17,7 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
#ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -49,7 +50,15 @@ struct fuzzer_rule {
};
/*
** A stem object is used to generate variants.
** A stem object is used to generate variants. It is also used to record
** previously generated outputs.
**
** Every stem is added to a hash table as it is output. Generation of
** duplicate stems is suppressed.
**
** Active stems (those that might generate new outputs) are kepts on a linked
** list sorted by increasing cost. The cost is the sum of rBaseCost and
** pRule->rCost.
*/
struct fuzzer_stem {
char *zBasis; /* Word being fuzzed */
@@ -83,6 +92,7 @@ struct fuzzer_cursor {
fuzzer_stem *pDone; /* Stems already processed to completion */
char *zBuf; /* Temporary use buffer */
int nBuf; /* Bytes allocated for zBuf */
fuzzer_rule nullRule; /* Null rule used first */
fuzzer_stem *apHash[FUZZER_HASH]; /* Hash of previously generated terms */
};
@@ -171,7 +181,6 @@ static int fuzzerOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
memset(pCur, 0, sizeof(*pCur));
pCur->pVtab = p;
*ppCursor = &pCur->base;
p->nCursor++;
if( p->nCursor==0 && p->pNewRule ){
unsigned int i;
fuzzer_rule *pX;
@@ -191,6 +200,7 @@ static int fuzzerOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
}
p->pRule = fuzzerMergeRules(p->pRule, pX);
}
p->nCursor++;
return SQLITE_OK;
}
@@ -221,35 +231,34 @@ static int fuzzerClose(sqlite3_vtab_cursor *cur){
fuzzerClearCursor(pCur, 0);
sqlite3_free(pCur->zBuf);
pCur->pVtab->nCursor--;
sqlite3_free(pCur);
return SQLITE_OK;
}
/*
** Compute the current output term for a fuzzer_stem.
*/
static int fuzzerComputeWord(
fuzzer_cursor *pCur,
fuzzer_stem *pStem
static int fuzzerRender(
fuzzer_stem *pStem, /* The stem to be rendered */
char **pzBuf, /* Write results into this buffer. realloc if needed */
int *pnBuf /* Size of the buffer */
){
const fuzzer_rule *pRule = pStem->pRule;
int n;
char *z;
n = pStem->nBasis;
if( pStem->n>=0 ) n += pRule->nTo - pRule->nFrom;
if( pCur->nBuf<n+1 ){
pCur->zBuf = sqlite3_realloc(pCur->zBuf, n+100);
if( pCur->zBuf==0 ) return SQLITE_NOMEM;
pCur->nBuf = n+100;
n = pStem->nBasis + pRule->nTo - pRule->nFrom;
if( (*pnBuf)<n+1 ){
(*pzBuf) = sqlite3_realloc((*pzBuf), n+100);
if( (*pzBuf)==0 ) return SQLITE_NOMEM;
(*pnBuf) = n+100;
}
n = pStem->n;
if( n<0 ){
memcpy(pCur->zBuf, pStem->zBasis, pStem->nBasis+1);
}else{
memcpy(pCur->zBuf, pStem->zBasis, n);
memcpy(&pCur->zBuf[n], pRule->zTo, pRule->nTo);
memcpy(&pCur->zBuf[n+pRule->nTo], &pStem->zBasis[n+pRule->nFrom],
pStem->nBasis-n-pRule->nFrom+1);
}
z = *pzBuf;
memcpy(z, pStem->zBasis, n);
memcpy(&z[n], pRule->zTo, pRule->nTo);
memcpy(&z[n+pRule->nTo], &pStem->zBasis[n+pRule->nFrom],
pStem->nBasis-n-pRule->nFrom+1);
return SQLITE_OK;
}
@@ -260,7 +269,7 @@ static int fuzzerComputeWord(
static unsigned int fuzzerHash(const char *z){
unsigned int h = 0;
while( *z ){ h = (h<<3) ^ (h>>29) ^ *(z++); }
return h%10007;
return h % FUZZER_HASH;
}
/*
@@ -270,9 +279,30 @@ static fuzzer_cost fuzzerCost(fuzzer_stem *pStem){
return pStem->rBaseCost + pStem->pRule->rCost;
}
/*
** Return 1 if the string to which the cursor is point has already
** been emitted. Return 0 if not. Return -1 on a memory allocation
** failures.
*/
static int fuzzerSeen(fuzzer_cursor *pCur, fuzzer_stem *pStem){
unsigned int h;
fuzzer_stem *pLookup;
if( fuzzerRender(pStem, &pCur->zBuf, &pCur->nBuf)==SQLITE_NOMEM ){
return -1;
}
h = fuzzerHash(pCur->zBuf);
pLookup = pCur->apHash[h];
while( pLookup && strcmp(pLookup->zBasis, pCur->zBuf)!=0 ){
pLookup = pLookup->pHash;
}
return pLookup!=0;
}
/*
** Advance a fuzzer_stem to its next value. Return 0 if there are
** no more values that can be generated by this fuzzer_stem.
** no more values that can be generated by this fuzzer_stem. Return
** -1 on a memory allocation failure.
*/
static int fuzzerAdvance(fuzzer_cursor *pCur, fuzzer_stem *pStem){
const fuzzer_rule *pRule;
@@ -283,21 +313,14 @@ static int fuzzerAdvance(fuzzer_cursor *pCur, fuzzer_stem *pStem){
|| memcmp(&pStem->zBasis[pStem->n], pRule->zFrom, pRule->nFrom)==0
){
/* Found a rewrite case. Make sure it is not a duplicate */
unsigned int h;
fuzzer_stem *pLookup;
fuzzerComputeWord(pCur, pStem);
h = fuzzerHash(pCur->zBuf);
pLookup = pCur->apHash[h];
while( pLookup && strcmp(pLookup->zBasis, pCur->zBuf)!=0 ){
pLookup = pLookup->pHash;
}
if( pLookup==0 ) return 1; /* A new output is found. */
int rc = fuzzerSeen(pCur, pStem);
if( rc<0 ) return -1;
if( rc==0 ) return 1;
}
}
pStem->n = -1;
pStem->pRule = pRule->pNext;
if( fuzzerCost(pStem)>pCur->rLimit ) pStem->pRule = 0;
if( pStem->pRule && fuzzerCost(pStem)>pCur->rLimit ) pStem->pRule = 0;
}
return 0;
}
@@ -310,6 +333,10 @@ static int fuzzerAdvance(fuzzer_cursor *pCur, fuzzer_stem *pStem){
static fuzzer_stem *fuzzerInsert(fuzzer_stem *pList, fuzzer_stem *pNew){
fuzzer_cost c1;
if( pList==0 ){
pNew->pNext = 0;
return pNew;
}
c1 = fuzzerCost(pNew);
if( c1 <= fuzzerCost(pList) ){
pNew->pNext = pList;
@@ -358,20 +385,30 @@ static fuzzer_stem *fuzzerNewStem(
** Advance a cursor to its next row of output
*/
static int fuzzerNext(sqlite3_vtab_cursor *cur){
fuzzer_cursor *pCur = (fuzzer_cursor*)pCur;
fuzzer_cursor *pCur = (fuzzer_cursor*)cur;
int rc;
fuzzer_stem *pStem, *pNew;
/* Use the element the cursor is currently point to to create
** a new stem and insert the new stem into the priority queue.
*/
fuzzerComputeWord(pCur, pCur->pStem);
pNew = fuzzerNewStem(pCur, pCur->zBuf, fuzzerCost(pCur->pStem));
if( pNew ){
if( fuzzerAdvance(pCur, pNew)==0 ){
pNew->pNext = pCur->pDone;
pCur->pDone = pNew;
pStem = pCur->pStem;
if( fuzzerCost(pStem)>0 ){
rc = fuzzerRender(pStem, &pCur->zBuf, &pCur->nBuf);
if( rc==SQLITE_NOMEM ) return SQLITE_NOMEM;
pNew = fuzzerNewStem(pCur, pCur->zBuf, fuzzerCost(pStem));
if( pNew ){
if( fuzzerAdvance(pCur, pNew)==0 ){
pNew->pNext = pCur->pDone;
pCur->pDone = pNew;
}else{
pCur->pStem = fuzzerInsert(pStem, pNew);
if( pCur->pStem==pNew ){
return SQLITE_OK;
}
}
}else{
pCur->pStem = fuzzerInsert(pCur->pStem, pNew);
return SQLITE_NOMEM;
}
}
@@ -381,7 +418,12 @@ static int fuzzerNext(sqlite3_vtab_cursor *cur){
while( (pStem = pCur->pStem)!=0 ){
if( fuzzerAdvance(pCur, pStem) ){
pCur->pStem = fuzzerInsert(pStem->pNext, pStem);
return SQLITE_OK; /* New word found */
if( pCur->pStem!=pStem && (rc = fuzzerSeen(pCur, pStem))!=0 ){
if( rc<0 ) return SQLITE_NOMEM;
continue;
}else{
return SQLITE_OK; /* New word found */
}
}
pCur->pStem = pStem->pNext;
pStem->pNext = pCur->pDone;
@@ -406,9 +448,10 @@ static int fuzzerFilter(
){
fuzzer_cursor *pCur = (fuzzer_cursor *)pVtabCursor;
const char *zWord = 0;
pCur->rLimit = 2147483647;
fuzzer_stem *pStem;
fuzzerClearCursor(pCur, 1);
pCur->rLimit = 2147483647;
if( idxNum==1 ){
zWord = (const char*)sqlite3_value_text(argv[0]);
}else if( idxNum==2 ){
@@ -418,8 +461,15 @@ static int fuzzerFilter(
pCur->rLimit = (fuzzer_cost)sqlite3_value_int(argv[1]);
}
if( zWord==0 ) zWord = "";
pCur->pStem = fuzzerNewStem(pCur, zWord, (fuzzer_cost)0);
if( pCur->pStem==0 ) return SQLITE_NOMEM;
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;
return SQLITE_OK;
}
@@ -431,7 +481,7 @@ static int fuzzerColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
fuzzer_cursor *pCur = (fuzzer_cursor*)cur;
if( i==0 ){
/* the "word" column */
if( fuzzerComputeWord(pCur, pCur->pStem)==SQLITE_NOMEM ){
if( fuzzerRender(pCur->pStem, &pCur->zBuf, &pCur->nBuf)==SQLITE_NOMEM ){
return SQLITE_NOMEM;
}
sqlite3_result_text(ctx, pCur->zBuf, -1, SQLITE_TRANSIENT);
@@ -567,17 +617,16 @@ static int fuzzerUpdate(
pVTab->zErrMsg = sqlite3_mprintf("cost must be positive");
return SQLITE_CONSTRAINT;
}
nFrom = strlen(zFrom)+1;
nTo = strlen(zTo)+1;
if( nTo<4 ) nTo = 4;
pRule = sqlite3_malloc( sizeof(*pRule) + nFrom + nTo - 4 );
nFrom = strlen(zFrom);
nTo = strlen(zTo);
pRule = sqlite3_malloc( sizeof(*pRule) + nFrom + nTo );
if( pRule==0 ){
return SQLITE_NOMEM;
}
pRule->zFrom = &pRule->zTo[nTo];
pRule->zFrom = &pRule->zTo[nTo+1];
pRule->nFrom = nFrom;
memcpy(pRule->zFrom, zFrom, nFrom);
memcpy(pRule->zTo, zTo, nTo);
memcpy(pRule->zFrom, zFrom, nFrom+1);
memcpy(pRule->zTo, zTo, nTo+1);
pRule->nTo = nTo;
pRule->rCost = rCost;
pRule->pNext = p->pNewRule;