]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Do not allow virtual table constructors to be called recursively.
authordrh <drh@noemail.net>
Thu, 21 May 2015 01:04:17 +0000 (01:04 +0000)
committerdrh <drh@noemail.net>
Thu, 21 May 2015 01:04:17 +0000 (01:04 +0000)
Cherrypick [0a72726da21581ab]

FossilOrigin-Name: 0f0694e4245083f6abb4ce104c39add45f2eb71a

ext/fts3/fts3.c
manifest
manifest.uuid
src/vtab.c
test/fts4content.test

index 421052b9377bb9a83212ec4f57a0ec8613f2257d..ca24befb3f758940b821516dbafdcd1a408f911f 100644 (file)
@@ -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. */ 
index 6282c260d7657a10d44a681ebadde57d505b9c12..161f8120cd2c808fad36210998f25c8255b27167 100644 (file)
--- 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
index 65918ae183f3e066c508f9d46128f7a5b62ece26..705f7ab61f981e6a44fd6177b3ede9b1044b3e68 100644 (file)
@@ -1 +1 @@
-a71e2a72c592f014051a00af9c7cb5c390612cb2
\ No newline at end of file
+0f0694e4245083f6abb4ce104c39add45f2eb71a
\ No newline at end of file
index c7221cd3b7e16571b6e84f01defa4fa8ade8cec5..f95ed2dce0660ef1c826de2c4dd93217688ee681 100644 (file)
@@ -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);
index 59c4199fa2653032e68a5a48a831e7994df20eb0..a956a6fb72ac86e850fe3161ace847c948131aab 100644 (file)
@@ -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