Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Skeleton code for the word-fuzzer virtual table. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | word-fuzzer |
Files: | files | file ages | folders |
SHA1: |
ea3a4ee136ff6699c3099178f0efaa8b |
User & Date: | drh 2011-03-26 15:05:27.457 |
Context
2011-03-26
| ||
19:04 | Added most of the logic. Simple test runs without segfaulting but does not give the correct answer. (check-in: fb4c31eac8 user: drh tags: word-fuzzer) | |
15:05 | Skeleton code for the word-fuzzer virtual table. (check-in: ea3a4ee136 user: drh tags: word-fuzzer) | |
2011-03-24
| ||
17:43 | Minor change to sqlite3Utf8Read() to make consistent with READ_UTF8() usage and avoid implementation defined usages of <<. Added some additional UTF-8 test cases. (check-in: 7173b3929f user: shaneh tags: trunk) | |
Changes
Changes to Makefile.in.
︙ | ︙ | |||
352 353 354 355 356 357 358 359 360 361 362 363 364 365 | $(TOP)/src/test_async.c \ $(TOP)/src/test_backup.c \ $(TOP)/src/test_btree.c \ $(TOP)/src/test_config.c \ $(TOP)/src/test_demovfs.c \ $(TOP)/src/test_devsym.c \ $(TOP)/src/test_func.c \ $(TOP)/src/test_hexio.c \ $(TOP)/src/test_init.c \ $(TOP)/src/test_intarray.c \ $(TOP)/src/test_journal.c \ $(TOP)/src/test_malloc.c \ $(TOP)/src/test_multiplex.c \ $(TOP)/src/test_mutex.c \ | > | 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 | $(TOP)/src/test_async.c \ $(TOP)/src/test_backup.c \ $(TOP)/src/test_btree.c \ $(TOP)/src/test_config.c \ $(TOP)/src/test_demovfs.c \ $(TOP)/src/test_devsym.c \ $(TOP)/src/test_func.c \ $(TOP)/src/test_fuzzer.c \ $(TOP)/src/test_hexio.c \ $(TOP)/src/test_init.c \ $(TOP)/src/test_intarray.c \ $(TOP)/src/test_journal.c \ $(TOP)/src/test_malloc.c \ $(TOP)/src/test_multiplex.c \ $(TOP)/src/test_mutex.c \ |
︙ | ︙ |
Changes to main.mk.
︙ | ︙ | |||
233 234 235 236 237 238 239 240 241 242 243 244 245 246 | $(TOP)/src/test_async.c \ $(TOP)/src/test_backup.c \ $(TOP)/src/test_btree.c \ $(TOP)/src/test_config.c \ $(TOP)/src/test_demovfs.c \ $(TOP)/src/test_devsym.c \ $(TOP)/src/test_func.c \ $(TOP)/src/test_hexio.c \ $(TOP)/src/test_init.c \ $(TOP)/src/test_intarray.c \ $(TOP)/src/test_journal.c \ $(TOP)/src/test_malloc.c \ $(TOP)/src/test_multiplex.c \ $(TOP)/src/test_mutex.c \ | > | 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 | $(TOP)/src/test_async.c \ $(TOP)/src/test_backup.c \ $(TOP)/src/test_btree.c \ $(TOP)/src/test_config.c \ $(TOP)/src/test_demovfs.c \ $(TOP)/src/test_devsym.c \ $(TOP)/src/test_func.c \ $(TOP)/src/test_fuzzer.c \ $(TOP)/src/test_hexio.c \ $(TOP)/src/test_init.c \ $(TOP)/src/test_intarray.c \ $(TOP)/src/test_journal.c \ $(TOP)/src/test_malloc.c \ $(TOP)/src/test_multiplex.c \ $(TOP)/src/test_mutex.c \ |
︙ | ︙ |
Changes to src/tclsqlite.c.
︙ | ︙ | |||
3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 | extern int Sqlitetestintarray_Init(Tcl_Interp*); extern int Sqlitetestvfs_Init(Tcl_Interp *); extern int SqlitetestStat_Init(Tcl_Interp*); extern int Sqlitetestrtree_Init(Tcl_Interp*); extern int Sqlitequota_Init(Tcl_Interp*); extern int Sqlitemultiplex_Init(Tcl_Interp*); extern int SqliteSuperlock_Init(Tcl_Interp*); #ifdef SQLITE_ENABLE_ZIPVFS extern int Zipvfs_Init(Tcl_Interp*); Zipvfs_Init(interp); #endif Sqliteconfig_Init(interp); | > | 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 | extern int Sqlitetestintarray_Init(Tcl_Interp*); extern int Sqlitetestvfs_Init(Tcl_Interp *); extern int SqlitetestStat_Init(Tcl_Interp*); extern int Sqlitetestrtree_Init(Tcl_Interp*); extern int Sqlitequota_Init(Tcl_Interp*); extern int Sqlitemultiplex_Init(Tcl_Interp*); extern int SqliteSuperlock_Init(Tcl_Interp*); extern int Sqlitetestfuzzer_Init(Tcl_Interp*); #ifdef SQLITE_ENABLE_ZIPVFS extern int Zipvfs_Init(Tcl_Interp*); Zipvfs_Init(interp); #endif Sqliteconfig_Init(interp); |
︙ | ︙ | |||
3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 | Sqlitetestintarray_Init(interp); Sqlitetestvfs_Init(interp); SqlitetestStat_Init(interp); Sqlitetestrtree_Init(interp); Sqlitequota_Init(interp); Sqlitemultiplex_Init(interp); SqliteSuperlock_Init(interp); Tcl_CreateObjCommand(interp,"load_testfixture_extensions",init_all_cmd,0,0); #ifdef SQLITE_SSE Sqlitetestsse_Init(interp); #endif } | > | 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 | Sqlitetestintarray_Init(interp); Sqlitetestvfs_Init(interp); SqlitetestStat_Init(interp); Sqlitetestrtree_Init(interp); Sqlitequota_Init(interp); Sqlitemultiplex_Init(interp); SqliteSuperlock_Init(interp); Sqlitetestfuzzer_Init(interp); Tcl_CreateObjCommand(interp,"load_testfixture_extensions",init_all_cmd,0,0); #ifdef SQLITE_SSE Sqlitetestsse_Init(interp); #endif } |
︙ | ︙ |
Added src/test_fuzzer.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 | /* ** 2011 March 24 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** Code for demonstartion virtual table that generates variations ** on an input word at increasing edit distances from the original. */ #include "sqlite3.h" #include <stdlib.h> #include <string.h> #include <assert.h> #ifndef SQLITE_OMIT_VIRTUALTABLE /* ** Forward declaration of objects used by this implementation */ typedef struct fuzzer_vtab fuzzer_vtab; typedef struct fuzzer_cursor fuzzer_cursor; typedef struct fuzzer_rule fuzzer_rule; typedef struct fuzzer_seen fuzzer_seen; typedef struct fuzzer_stem fuzzer_stem; /* ** Each transformation rule is stored as an instance of this object. ** All rules are kept on a linked list sorted by rCost. */ struct fuzzer_rule { fuzzer_rule *pNext; /* Next rule in order of increasing rCost */ float rCost; /* Cost of this transformation */ char *zFrom; /* Transform from */ char zTo[4]; /* Transform to (extra space appended) */ }; /* ** When generating fuzzed words, we have to remember all previously ** generated terms in order to suppress duplicates. Each previously ** generated term is an instance of the following structure. */ struct fuzzer_seen { fuzzer_seen *pNext; /* Next with the same hash */ char zWord[4]; /* The generated term. */ }; /* ** A stem object is used to generate variants. */ struct fuzzer_stem { char *zBasis; /* Word being fuzzed */ fuzzer_rule *pRule; /* Next rule to apply */ int n; /* Apply rule at this character offset */ float rBaseCost; /* Base cost of getting to zBasis */ float rCost; /* rBaseCost + cost of applying pRule at n */ fuzzer_stem *pNext; /* Next stem in rCost order */ }; /* ** A fuzzer virtual-table object */ struct fuzzer_vtab { sqlite3_vtab base; /* Base class - must be first */ char *zClassName; /* Name of this class. Default: "fuzzer" */ fuzzer_rule *pRule; /* All active rules in this fuzzer */ fuzzer_rule *pNewRule; /* New rules to add when last cursor expires */ int nCursor; /* Number of active cursors */ }; /* A fuzzer cursor object */ struct fuzzer_cursor { sqlite3_vtab_cursor base; /* Base class - must be first */ float rMax; /* Maximum cost of any term */ fuzzer_stem *pStem; /* Sorted list of stems for generating new terms */ int nSeen; /* Number of terms already generated */ int nHash; /* Number of slots in apHash */ fuzzer_seen **apHash; /* Hash table of previously generated terms */ }; /* Methods for the fuzzer module */ static int fuzzerConnect( sqlite3 *db, void *pAux, int argc, const char *const*argv, sqlite3_vtab **ppVtab, char **pzErr ){ fuzzer_vtab *pNew; char *zSql; int n; if( strcmp(argv[1],"temp")!=0 ){ *pzErr = sqlite3_mprintf("%s virtual tables must be TEMP", argv[0]); return SQLITE_ERROR; } n = strlen(argv[0]) + 1; pNew = sqlite3_malloc( sizeof(*pNew) + n ); if( pNew==0 ) return SQLITE_NOMEM; pNew->zClassName = (char*)&pNew[1]; memcpy(pNew->zClassName, argv[0], n); zSql = sqlite3_mprintf( "CREATE TABLE x(word, distance, cFrom, cTo, cost, \"%w\" HIDDEN)", argv[2] ); sqlite3_declare_vtab(db, zSql); sqlite3_free(zSql); memset(pNew, 0, sizeof(*pNew)); *ppVtab = &pNew->base; return SQLITE_OK; } /* 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 ); do{ while( p->pRule ){ fuzzer_rule *pRule = p->pRule; p->pRule = pRule->pNext; sqlite3_free(pRule); } p->pRule = p->pNewRule; p->pNewRule = 0; }while( p->pRule ); sqlite3_free(p); return SQLITE_OK; } /* The xDisconnect and xDestroy methods are also the same */ /* ** The two input rule lists are both sorted in order of increasing ** cost. Merge them together into a single list, sorted by cost, and ** return a pointer to the head of that list. */ static fuzzer_rule *fuzzerMergeRules(fuzzer_rule *pA, fuzzer_rule *pB){ fuzzer_rule head; fuzzer_rule *pTail; pTail = &head; while( pA && pB ){ if( pA->rCost<=pB->rCost ){ pTail->pNext = pA; pTail = pA; pA = pA->pNext; }else{ pTail->pNext = pB; pTail = pB; pB = pB->pNext; } } if( pA==0 ){ pTail->pNext = pB; }else{ pTail->pNext = pA; } return head.pNext; } /* ** Open a new fuzzer cursor. */ static int fuzzerOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ fuzzer_vtab *p = (fuzzer_vtab*)pVTab; fuzzer_cursor *pCur; pCur = sqlite3_malloc( sizeof(*pCur) ); if( pCur==0 ) return SQLITE_NOMEM; memset(pCur, 0, sizeof(*pCur)); *ppCursor = &pCur->base; if( p->nCursor==0 && p->pNewRule ){ unsigned int i; fuzzer_rule *pX; fuzzer_rule *a[15]; for(i=0; i<sizeof(a)/sizeof(a[0]); i++) a[i] = 0; while( (pX = p->pNewRule)!=0 ){ p->pNewRule = pX->pNext; pX->pNext = 0; for(i=0; a[i] && i<sizeof(a)/sizeof(a[0])-1; i++){ pX = fuzzerMergeRules(a[i], pX); a[i] = 0; } a[i] = fuzzerMergeRules(a[i], pX); } for(pX=a[0], i=1; i<sizeof(a)/sizeof(a[0]); i++){ pX = fuzzerMergeRules(a[i], pX); } p->pRule = fuzzerMergeRules(p->pRule, pX); } return SQLITE_OK; } /* ** Close a fuzzer cursor. */ static int fuzzerClose(sqlite3_vtab_cursor *cur){ fuzzer_cursor *pCur = (fuzzer_cursor *)cur; int i; for(i=0; i<pCur->nHash; i++){ fuzzer_seen *pSeen = pCur->apHash[i]; while( pSeen ){ fuzzer_seen *pNext = pSeen->pNext; sqlite3_free(pSeen); pSeen = pNext; } } sqlite3_free(pCur->apHash); while( pCur->pStem ){ fuzzer_stem *pStem = pCur->pStem; pCur->pStem = pStem->pNext; sqlite3_free(pStem); } sqlite3_free(pCur); return SQLITE_OK; } static int fuzzerNext(sqlite3_vtab_cursor *cur){ return 0; } static int fuzzerFilter( sqlite3_vtab_cursor *pVtabCursor, int idxNum, const char *idxStr, int argc, sqlite3_value **argv ){ fuzzer_cursor *pCur = (fuzzer_cursor *)pVtabCursor; return fuzzerNext(pVtabCursor); } static int fuzzerColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ fuzzer_cursor *pCur = (fuzzer_cursor*)cur; return SQLITE_OK; } static int fuzzerRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ *pRowid = 0; return SQLITE_OK; } static int fuzzerEof(sqlite3_vtab_cursor *cur){ fuzzer_cursor *pCur = (fuzzer_cursor*)cur; return 1; } static int fuzzerBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ return SQLITE_OK; } /* ** Disallow all attempts to DELETE or UPDATE. Only INSERTs are allowed. ** ** On an insert, the cFrom, cTo, and cost columns are used to construct ** a new rule. All other columns are ignored. The rule is ignored ** if cFrom and cTo are identical. A NULL value for cFrom or cTo is ** interpreted as an empty string. The cost must be positive. */ static int fuzzerUpdate( sqlite3_vtab *pVTab, int argc, sqlite3_value **argv, sqlite_int64 *pRowid ){ fuzzer_vtab *p = (fuzzer_vtab*)pVTab; fuzzer_rule *pRule; const char *zFrom; int nFrom; const char *zTo; int nTo; float rCost; if( argc!=8 ){ sqlite3_free(pVTab->zErrMsg); pVTab->zErrMsg = sqlite3_mprintf("cannot delete from a %s virtual table", p->zClassName); return SQLITE_CONSTRAINT; } if( sqlite3_value_type(argv[0])!=SQLITE_NULL ){ sqlite3_free(pVTab->zErrMsg); pVTab->zErrMsg = sqlite3_mprintf("cannot update a %s virtual table", p->zClassName); return SQLITE_CONSTRAINT; } zFrom = (char*)sqlite3_value_text(argv[4]); if( zFrom==0 ) zFrom = ""; zTo = (char*)sqlite3_value_text(argv[5]); if( zTo==0 ) zTo = ""; if( strcmp(zFrom,zTo)==0 ){ /* Silently ignore null transformations */ return SQLITE_OK; } rCost = (float)sqlite3_value_double(argv[6]); if( rCost<=0 ){ sqlite3_free(pVTab->zErrMsg); 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 ); if( pRule==0 ){ return SQLITE_NOMEM; } pRule->zFrom = &pRule->zTo[nTo]; memcpy(pRule->zFrom, zFrom, nFrom); memcpy(pRule->zTo, zTo, nTo); pRule->rCost = rCost; pRule->pNext = p->pNewRule; p->pNewRule = pRule; return SQLITE_OK; } /* ** A virtual table module that provides read-only access to a ** Tcl global variable namespace. */ static sqlite3_module fuzzerModule = { 0, /* iVersion */ fuzzerConnect, fuzzerConnect, fuzzerBestIndex, fuzzerDisconnect, fuzzerDisconnect, fuzzerOpen, /* xOpen - open a cursor */ fuzzerClose, /* xClose - close a cursor */ fuzzerFilter, /* xFilter - configure scan constraints */ fuzzerNext, /* xNext - advance a cursor */ fuzzerEof, /* xEof - check for end of scan */ fuzzerColumn, /* xColumn - read data */ fuzzerRowid, /* xRowid - read data */ fuzzerUpdate, /* xUpdate - INSERT */ 0, /* xBegin */ 0, /* xSync */ 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ }; #endif /* SQLITE_OMIT_VIRTUALTABLE */ /* ** Register the fuzzer virtual table */ int fuzzer_register(sqlite3 *db){ int rc = SQLITE_OK; #ifndef SQLITE_OMIT_VIRTUALTABLE rc = sqlite3_create_module(db, "fuzzer", &fuzzerModule, 0); #endif return rc; } #ifdef SQLITE_TEST #include <tcl.h> /* ** Decode a pointer to an sqlite3 object. */ extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb); /* ** Register the echo virtual table module. */ static int register_fuzzer_module( ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int objc, /* Number of arguments */ Tcl_Obj *CONST objv[] /* Command arguments */ ){ sqlite3 *db; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "DB"); return TCL_ERROR; } if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; fuzzer_register(db); return TCL_OK; } /* ** Register commands with the TCL interpreter. */ int Sqlitetestfuzzer_Init(Tcl_Interp *interp){ static struct { char *zName; Tcl_ObjCmdProc *xProc; void *clientData; } aObjCmd[] = { { "register_fuzzer_module", register_fuzzer_module, 0 }, }; int i; for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, aObjCmd[i].clientData, 0); } return TCL_OK; } #endif /* SQLITE_TEST */ |
Added test/fuzzer1.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | # 2011 March 25 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for TCL interface to the # SQLite library. # # The focus of the tests is the word-fuzzer virtual table. # set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable !vtab { finish_test return } register_fuzzer_module db do_test fuzzer1-1.0 { catchsql {CREATE VIRTUAL TABLE fault1 USING fuzzer;} } {1 {fuzzer virtual tables must be TEMP}} do_test fuzzer1-1.1 { db eval {CREATE VIRTUAL TABLE temp.f1 USING fuzzer;} } {} do_test fuzzer1-1.2 { db eval { INSERT INTO f1(cfrom, cto, cost) VALUES('e','a',0.1); INSERT INTO f1(cfrom, cto, cost) VALUES('a','e',0.1); INSERT INTO f1(cfrom, cto, cost) VALUES('e','o',0.1); } } {} finish_test |