From: drh Date: Thu, 21 May 2015 01:04:17 +0000 (+0000) Subject: Do not allow virtual table constructors to be called recursively. X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=faab2a699b845786b933df185fcb3e59591596cc;p=thirdparty%2Fsqlite.git Do not allow virtual table constructors to be called recursively. Cherrypick [0a72726da21581ab] FossilOrigin-Name: 0f0694e4245083f6abb4ce104c39add45f2eb71a --- diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c index 421052b937..ca24befb3f 100644 --- a/ext/fts3/fts3.c +++ b/ext/fts3/fts3.c @@ -971,7 +971,8 @@ static int fts3ContentColumns( const char *zTbl, /* Name of content table */ const char ***pazCol, /* OUT: Malloc'd array of column names */ int *pnCol, /* OUT: Size of array *pazCol */ - int *pnStr /* OUT: Bytes of string content */ + int *pnStr, /* OUT: Bytes of string content */ + char **pzErr /* OUT: error message */ ){ int rc = SQLITE_OK; /* Return code */ char *zSql; /* "SELECT *" statement on zTbl */ @@ -982,6 +983,9 @@ static int fts3ContentColumns( rc = SQLITE_NOMEM; }else{ rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); + if( rc!=SQLITE_OK ){ + *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db)); + } } sqlite3_free(zSql); @@ -1215,7 +1219,7 @@ static int fts3InitVtab( if( nCol==0 ){ sqlite3_free((void*)aCol); aCol = 0; - rc = fts3ContentColumns(db, argv[1], zContent, &aCol, &nCol, &nString); + rc = fts3ContentColumns(db, argv[1], zContent,&aCol,&nCol,&nString,pzErr); /* If a languageid= option was specified, remove the language id ** column from the aCol[] array. */ diff --git a/manifest b/manifest index 6282c260d7..161f8120cd 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\s".open"\scommand\sto\sthe\scommand-line\sshell.\nCherrypick\sfrom\s[21eccb919441]. -D 2015-05-21T00:50:37.386 +C Do\snot\sallow\svirtual\stable\sconstructors\sto\sbe\scalled\srecursively.\nCherrypick\s[0a72726da21581ab] +D 2015-05-21T01:04:17.693 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 2f37e468503dbe79d35c9f6dffcf3fae1ae9ec20 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -63,7 +63,7 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51 F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a F ext/fts3/README.tokenizers 998756696647400de63d5ba60e9655036cb966e9 F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d -F ext/fts3/fts3.c a62e09140c00f9c401efca661e7f2ae9909194f6 +F ext/fts3/fts3.c a2a545a38d9d4d2574608da189284b5f8ba00d6d F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe F ext/fts3/fts3Int.h d1d7f964ddee067bcd16a6af4ba7ecf66220056d F ext/fts3/fts3_aux.c 5205182bd8f372782597888156404766edf5781e @@ -249,7 +249,7 @@ F src/vdbeblob.c 32f2a4899d67f69634ea4dd93e3f651936d732cb F src/vdbemem.c fb0ac964ccbcd94f595eb993c05bfd9c52468a4a F src/vdbesort.c b25814d385895544ebc8118245c8311ded7f81c9 F src/vdbetrace.c d6e50e04e1ec498150e519058f617d91b8f5c843 -F src/vtab.c ab90fb600a3f5e4b7c48d22a4cdb2d6b23239847 +F src/vtab.c a078fb78c0f7bfa4a365495badf53581d512b648 F src/wal.c 7bb3ad807afc7973406c805d5157ec7a2f65e146 F src/wal.h 29c197540b19044e6cd73487017e5e47a1d3dac6 F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f @@ -495,7 +495,7 @@ F test/fts3shared.test 8bb266521d7c5495c0ae522bb4d376ad5387d4a2 F test/fts3snippet.test 8e956051221a34c7daeb504f023cb54d5fa5a8b2 F test/fts3sort.test 95be0b19d7e41c44b29014f13ea8bddd495fd659 F test/fts4aa.test 6e7f90420b837b2c685f3bcbe84c868492d40a68 -F test/fts4content.test 17b2360f7d1a9a7e5aa8022783f5c5731b6dfd4f +F test/fts4content.test 655e5036c98272c93d8ec0eb8c6b7100928faeae F test/fts4langid.test 2081c357bb6f170f34ef8e08c6abb88002b95c69 F test/func.test 6c5ce11e3a0021ca3c0649234e2d4454c89110ca F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f @@ -992,11 +992,8 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P 00bb9c9ce4f465e6ac321ced2a9d0062dc364669 -Q +21eccb919441bd111ba414dde3f00862822e2c99 -R feff229c300afcfceea2f853e4bccd1c -T *branch * branch-3.7.11 -T *sym-branch-3.7.11 * -T -sym-trunk * +P a71e2a72c592f014051a00af9c7cb5c390612cb2 +Q +0a72726da21581ab16cb3e964bd825b8f2e931e4 +R 8a644e69b3a7726913eb23696e1937e1 U drh -Z 03df1d8360641e51d6edb83127f6df82 +Z 95187feec4c184bfd6cb010b3ad956ea diff --git a/manifest.uuid b/manifest.uuid index 65918ae183..705f7ab61f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a71e2a72c592f014051a00af9c7cb5c390612cb2 \ No newline at end of file +0f0694e4245083f6abb4ce104c39add45f2eb71a \ No newline at end of file diff --git a/src/vtab.c b/src/vtab.c index c7221cd3b7..f95ed2dce0 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -24,6 +24,8 @@ struct VtabCtx { Table *pTab; VTable *pVTable; + VtabCtx *pPrior; /* Parent context (if any) */ + int bDeclared; /* True after sqlite3_declare_vtab() is called */ }; /* @@ -453,8 +455,20 @@ static int vtabCallConstructor( const char *const*azArg = (const char *const*)pTab->azModuleArg; int nArg = pTab->nModuleArg; char *zErr = 0; - char *zModuleName = sqlite3MPrintf(db, "%s", pTab->zName); + char *zModuleName; + VtabCtx *pCtx; + + /* Check that the virtual-table is not already being initialized */ + for(pCtx=db->pVtabCtx; pCtx; pCtx=pCtx->pPrior){ + if( pCtx->pTab==pTab ){ + *pzErr = sqlite3MPrintf(db, + "vtable constructor called recursively: %s", pTab->zName + ); + return SQLITE_LOCKED; + } + } + zModuleName = sqlite3MPrintf(db, "%s", pTab->zName); if( !zModuleName ){ return SQLITE_NOMEM; } @@ -472,10 +486,13 @@ static int vtabCallConstructor( assert( xConstruct ); sCtx.pTab = pTab; sCtx.pVTable = pVTable; + sCtx.pPrior = db->pVtabCtx; + sCtx.bDeclared = 0; db->pVtabCtx = &sCtx; rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr); - db->pVtabCtx = 0; + db->pVtabCtx = sCtx.pPrior; if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; + assert( sCtx.pTab==pTab ); if( SQLITE_OK!=rc ){ if( zErr==0 ){ @@ -490,7 +507,7 @@ static int vtabCallConstructor( ** the sqlite3_vtab object if successful. */ pVTable->pVtab->pModule = pMod->pModule; pVTable->nRef = 1; - if( sCtx.pTab ){ + if( sCtx.bDeclared==0 ){ const char *zFormat = "vtable constructor did not declare schema: %s"; *pzErr = sqlite3MPrintf(db, zFormat, pTab->zName); sqlite3VtabUnlock(pVTable); @@ -660,18 +677,19 @@ int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){ ** virtual table module. */ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ + VtabCtx *pCtx = db->pVtabCtx; Parse *pParse; - int rc = SQLITE_OK; Table *pTab; char *zErr = 0; sqlite3_mutex_enter(db->mutex); - if( !db->pVtabCtx || !(pTab = db->pVtabCtx->pTab) ){ + if( !pCtx || pCtx->bDeclared ){ sqlite3Error(db, SQLITE_MISUSE, 0); sqlite3_mutex_leave(db->mutex); return SQLITE_MISUSE_BKPT; } + pTab = pCtx->pTab; assert( (pTab->tabFlags & TF_Virtual)!=0 ); pParse = sqlite3StackAllocZero(db, sizeof(*pParse)); @@ -694,7 +712,7 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ pParse->pNewTable->nCol = 0; pParse->pNewTable->aCol = 0; } - db->pVtabCtx->pTab = 0; + pCtx->bDeclared = 1; }else{ sqlite3Error(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr); sqlite3DbFree(db, zErr); diff --git a/test/fts4content.test b/test/fts4content.test index 59c4199fa2..a956a6fb72 100644 --- a/test/fts4content.test +++ b/test/fts4content.test @@ -46,6 +46,9 @@ ifcapable !fts3 { # 8.* - Test that if the content=xxx and prefix options are used together, # the 'rebuild' command still works. # +# 11.* - Test that circular references (e.g. "t1(content=t1)") are +# detected. +# do_execsql_test 1.1.1 { CREATE TABLE t1(a, b, c); @@ -404,7 +407,7 @@ do_execsql_test 5.1.7 { # do_catchsql_test 6.1.1 { CREATE VIRTUAL TABLE ft7 USING fts4(content=t7); -} {1 {vtable constructor failed: ft7}} +} {1 {no such table: main.t7}} do_execsql_test 6.2.1 { CREATE TABLE t7(one, two); @@ -431,7 +434,7 @@ do_execsql_test 6.2.3 { } do_catchsql_test 6.2.4 { SELECT * FROM ft7; -} {1 {vtable constructor failed: ft7}} +} {1 {no such table: main.t7}} do_execsql_test 6.2.5 { CREATE TABLE t7(x, y); INSERT INTO t7 VALUES('A B', 'B A'); @@ -522,4 +525,49 @@ do_execsql_test 8.4 { SELECT rowid FROM ft10 WHERE a MATCH 'ab*'; } {1 2 3} do_execsql_test 8.5 { SELECT rowid FROM ft10 WHERE b MATCH 'abav*'; } {3} do_execsql_test 8.6 { SELECT rowid FROM ft10 WHERE ft10 MATCH 'abas*'; } {1} +#------------------------------------------------------------------------- +# Test cases 9.* +# +reset_db +register_echo_module [sqlite3_connection_pointer db] + +do_execsql_test 9.1 { + CREATE TABLE tbl1(a, b); + INSERT INTO tbl1 VALUES('a b', 'c d'); + INSERT INTO tbl1 VALUES('e f', 'a b'); + CREATE VIRTUAL TABLE e1 USING echo(tbl1); + CREATE VIRTUAL TABLE ft1 USING fts4(content=e1); + INSERT INTO ft1(ft1) VALUES('rebuild'); +} + +do_execsql_test 9.2 { + SELECT rowid, * FROM ft1 WHERE ft1 MATCH 'e' +} {2 {e f} {a b}} + +do_execsql_test 9.3 { + SELECT rowid, * FROM ft1 WHERE ft1 MATCH 'a' +} {1 {a b} {c d} 2 {e f} {a b}} + +do_execsql_test 9.4 { + DELETE FROM ft1 WHERE docid=1; +} + +do_execsql_test 9.5 { + SELECT rowid, * FROM ft1 WHERE ft1 MATCH 'a' +} {2 {e f} {a b}} + +do_execsql_test 9.6 { + INSERT INTO ft1(ft1) VALUES('rebuild'); + SELECT rowid, * FROM ft1 WHERE ft1 MATCH 'a' +} {1 {a b} {c d} 2 {e f} {a b}} + +#------------------------------------------------------------------------- +# Test cases 11.* +# +reset_db + +do_catchsql_test 11.1 { + CREATE VIRTUAL TABLE x1 USING fts4(content=x1); +} {1 {vtable constructor called recursively: x1}} + finish_test