/ Check-in [0f0694e4]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Do not allow virtual table constructors to be called recursively. Cherrypick [0a72726da21581ab]
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | branch-3.7.11
Files: files | file ages | folders
SHA1: 0f0694e4245083f6abb4ce104c39add45f2eb71a
User & Date: drh 2015-05-21 01:04:17
Context
2015-05-21
02:07
When parsing the schema, ignore any SQL that does not begin with "CREATE". Cherrypick of [d3c00d61581c] with additional changes. check-in: 09784f37 user: drh tags: branch-3.7.11
01:04
Do not allow virtual table constructors to be called recursively. Cherrypick [0a72726da21581ab] check-in: 0f0694e4 user: drh tags: branch-3.7.11
00:50
Add the ".open" command to the command-line shell. Cherrypick from [21eccb919441]. check-in: a71e2a72 user: drh tags: branch-3.7.11
2015-04-10
07:55
Do not allow virtual table constructors to be called recursively. check-in: 0a72726d user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/fts3/fts3.c.

   967    967   */
   968    968   static int fts3ContentColumns(
   969    969     sqlite3 *db,                    /* Database handle */
   970    970     const char *zDb,                /* Name of db (i.e. "main", "temp" etc.) */
   971    971     const char *zTbl,               /* Name of content table */
   972    972     const char ***pazCol,           /* OUT: Malloc'd array of column names */
   973    973     int *pnCol,                     /* OUT: Size of array *pazCol */
   974         -  int *pnStr                      /* OUT: Bytes of string content */
          974  +  int *pnStr,                     /* OUT: Bytes of string content */
          975  +  char **pzErr                    /* OUT: error message */
   975    976   ){
   976    977     int rc = SQLITE_OK;             /* Return code */
   977    978     char *zSql;                     /* "SELECT *" statement on zTbl */  
   978    979     sqlite3_stmt *pStmt = 0;        /* Compiled version of zSql */
   979    980   
   980    981     zSql = sqlite3_mprintf("SELECT * FROM %Q.%Q", zDb, zTbl);
   981    982     if( !zSql ){
   982    983       rc = SQLITE_NOMEM;
   983    984     }else{
   984    985       rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
          986  +    if( rc!=SQLITE_OK ){
          987  +      *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
          988  +    }
   985    989     }
   986    990     sqlite3_free(zSql);
   987    991   
   988    992     if( rc==SQLITE_OK ){
   989    993       const char **azCol;           /* Output array */
   990    994       int nStr = 0;                 /* Size of all column names (incl. 0x00) */
   991    995       int nCol;                     /* Number of table columns */
................................................................................
  1211   1215       sqlite3_free(zCompress); 
  1212   1216       sqlite3_free(zUncompress); 
  1213   1217       zCompress = 0;
  1214   1218       zUncompress = 0;
  1215   1219       if( nCol==0 ){
  1216   1220         sqlite3_free((void*)aCol); 
  1217   1221         aCol = 0;
  1218         -      rc = fts3ContentColumns(db, argv[1], zContent, &aCol, &nCol, &nString);
         1222  +      rc = fts3ContentColumns(db, argv[1], zContent,&aCol,&nCol,&nString,pzErr);
  1219   1223   
  1220   1224         /* If a languageid= option was specified, remove the language id
  1221   1225         ** column from the aCol[] array. */ 
  1222   1226         if( rc==SQLITE_OK && zLanguageid ){
  1223   1227           int j;
  1224   1228           for(j=0; j<nCol; j++){
  1225   1229             if( sqlite3_stricmp(zLanguageid, aCol[j])==0 ){

Changes to src/vtab.c.

    20     20   ** this struct allocated on the stack. It is used by the implementation of 
    21     21   ** the sqlite3_declare_vtab() and sqlite3_vtab_config() APIs, both of which
    22     22   ** are invoked only from within xCreate and xConnect methods.
    23     23   */
    24     24   struct VtabCtx {
    25     25     Table *pTab;
    26     26     VTable *pVTable;
           27  +  VtabCtx *pPrior;    /* Parent context (if any) */
           28  +  int bDeclared;      /* True after sqlite3_declare_vtab() is called */
    27     29   };
    28     30   
    29     31   /*
    30     32   ** The actual function that does the work of creating a new module.
    31     33   ** This function implements the sqlite3_create_module() and
    32     34   ** sqlite3_create_module_v2() interfaces.
    33     35   */
................................................................................
   449    451   ){
   450    452     VtabCtx sCtx;
   451    453     VTable *pVTable;
   452    454     int rc;
   453    455     const char *const*azArg = (const char *const*)pTab->azModuleArg;
   454    456     int nArg = pTab->nModuleArg;
   455    457     char *zErr = 0;
   456         -  char *zModuleName = sqlite3MPrintf(db, "%s", pTab->zName);
          458  +  char *zModuleName;
          459  +  VtabCtx *pCtx;
   457    460   
          461  +  /* Check that the virtual-table is not already being initialized */
          462  +  for(pCtx=db->pVtabCtx; pCtx; pCtx=pCtx->pPrior){
          463  +    if( pCtx->pTab==pTab ){
          464  +      *pzErr = sqlite3MPrintf(db, 
          465  +          "vtable constructor called recursively: %s", pTab->zName
          466  +      );
          467  +      return SQLITE_LOCKED;
          468  +    }
          469  +  }
          470  +
          471  +  zModuleName = sqlite3MPrintf(db, "%s", pTab->zName);
   458    472     if( !zModuleName ){
   459    473       return SQLITE_NOMEM;
   460    474     }
   461    475   
   462    476     pVTable = sqlite3DbMallocZero(db, sizeof(VTable));
   463    477     if( !pVTable ){
   464    478       sqlite3DbFree(db, zModuleName);
................................................................................
   468    482     pVTable->pMod = pMod;
   469    483   
   470    484     /* Invoke the virtual table constructor */
   471    485     assert( &db->pVtabCtx );
   472    486     assert( xConstruct );
   473    487     sCtx.pTab = pTab;
   474    488     sCtx.pVTable = pVTable;
          489  +  sCtx.pPrior = db->pVtabCtx;
          490  +  sCtx.bDeclared = 0;
   475    491     db->pVtabCtx = &sCtx;
   476    492     rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr);
   477         -  db->pVtabCtx = 0;
          493  +  db->pVtabCtx = sCtx.pPrior;
   478    494     if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
          495  +  assert( sCtx.pTab==pTab );
   479    496   
   480    497     if( SQLITE_OK!=rc ){
   481    498       if( zErr==0 ){
   482    499         *pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName);
   483    500       }else {
   484    501         *pzErr = sqlite3MPrintf(db, "%s", zErr);
   485    502         sqlite3_free(zErr);
................................................................................
   486    503       }
   487    504       sqlite3DbFree(db, pVTable);
   488    505     }else if( ALWAYS(pVTable->pVtab) ){
   489    506       /* Justification of ALWAYS():  A correct vtab constructor must allocate
   490    507       ** the sqlite3_vtab object if successful.  */
   491    508       pVTable->pVtab->pModule = pMod->pModule;
   492    509       pVTable->nRef = 1;
   493         -    if( sCtx.pTab ){
          510  +    if( sCtx.bDeclared==0 ){
   494    511         const char *zFormat = "vtable constructor did not declare schema: %s";
   495    512         *pzErr = sqlite3MPrintf(db, zFormat, pTab->zName);
   496    513         sqlite3VtabUnlock(pVTable);
   497    514         rc = SQLITE_ERROR;
   498    515       }else{
   499    516         int iCol;
   500    517         /* If everything went according to plan, link the new VTable structure
................................................................................
   656    673   
   657    674   /*
   658    675   ** This function is used to set the schema of a virtual table.  It is only
   659    676   ** valid to call this function from within the xCreate() or xConnect() of a
   660    677   ** virtual table module.
   661    678   */
   662    679   int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
          680  +  VtabCtx *pCtx = db->pVtabCtx;
   663    681     Parse *pParse;
   664         -
   665    682     int rc = SQLITE_OK;
   666    683     Table *pTab;
   667    684     char *zErr = 0;
   668    685   
   669    686     sqlite3_mutex_enter(db->mutex);
   670         -  if( !db->pVtabCtx || !(pTab = db->pVtabCtx->pTab) ){
          687  +  if( !pCtx || pCtx->bDeclared ){
   671    688       sqlite3Error(db, SQLITE_MISUSE, 0);
   672    689       sqlite3_mutex_leave(db->mutex);
   673    690       return SQLITE_MISUSE_BKPT;
   674    691     }
          692  +  pTab = pCtx->pTab;
   675    693     assert( (pTab->tabFlags & TF_Virtual)!=0 );
   676    694   
   677    695     pParse = sqlite3StackAllocZero(db, sizeof(*pParse));
   678    696     if( pParse==0 ){
   679    697       rc = SQLITE_NOMEM;
   680    698     }else{
   681    699       pParse->declareVtab = 1;
................................................................................
   690    708       ){
   691    709         if( !pTab->aCol ){
   692    710           pTab->aCol = pParse->pNewTable->aCol;
   693    711           pTab->nCol = pParse->pNewTable->nCol;
   694    712           pParse->pNewTable->nCol = 0;
   695    713           pParse->pNewTable->aCol = 0;
   696    714         }
   697         -      db->pVtabCtx->pTab = 0;
          715  +      pCtx->bDeclared = 1;
   698    716       }else{
   699    717         sqlite3Error(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr);
   700    718         sqlite3DbFree(db, zErr);
   701    719         rc = SQLITE_ERROR;
   702    720       }
   703    721       pParse->declareVtab = 0;
   704    722     

Changes to test/fts4content.test.

    42     42   #   7.* - Test that if content=xxx is specified and table xxx does not
    43     43   #         exist, the FTS table can still be used for INSERT and some
    44     44   #         SELECT statements.
    45     45   #
    46     46   #   8.* - Test that if the content=xxx and prefix options are used together,
    47     47   #         the 'rebuild' command still works.
    48     48   #
           49  +#   11.* - Test that circular references (e.g. "t1(content=t1)") are
           50  +#          detected.
           51  +#
    49     52   
    50     53   do_execsql_test 1.1.1 {
    51     54     CREATE TABLE t1(a, b, c);
    52     55     INSERT INTO t1 VALUES('w x', 'x y', 'y z');
    53     56     CREATE VIRTUAL TABLE ft1 USING fts4(content=t1);
    54     57   }
    55     58   
................................................................................
   400    403   }
   401    404   
   402    405   #-------------------------------------------------------------------------
   403    406   # Test cases 6.* test 
   404    407   # 
   405    408   do_catchsql_test 6.1.1 {
   406    409     CREATE VIRTUAL TABLE ft7 USING fts4(content=t7);
   407         -} {1 {vtable constructor failed: ft7}}
          410  +} {1 {no such table: main.t7}}
   408    411   
   409    412   do_execsql_test 6.2.1 {
   410    413     CREATE TABLE t7(one, two);
   411    414     CREATE VIRTUAL TABLE ft7 USING fts4(content=t7);
   412    415     INSERT INTO t7 VALUES('A B', 'B A');
   413    416     INSERT INTO t7 VALUES('C D', 'A A');
   414    417     SELECT * FROM ft7;
................................................................................
   427    430     SELECT name FROM sqlite_master WHERE name LIKE '%t7%'
   428    431   } {
   429    432     ft7 ft7_segments ft7_segdir sqlite_autoindex_ft7_segdir_1 
   430    433     ft7_docsize ft7_stat
   431    434   }
   432    435   do_catchsql_test 6.2.4 {
   433    436     SELECT * FROM ft7;
   434         -} {1 {vtable constructor failed: ft7}}
          437  +} {1 {no such table: main.t7}}
   435    438   do_execsql_test 6.2.5 {
   436    439     CREATE TABLE t7(x, y);
   437    440     INSERT INTO t7 VALUES('A B', 'B A');
   438    441     INSERT INTO t7 VALUES('C D', 'A A');
   439    442     SELECT * FROM ft7;
   440    443   } {
   441    444     {A B} {B A} {C D} {A A}
................................................................................
   517    520   }
   518    521   
   519    522   do_execsql_test 8.2 { SELECT * FROM ft10 WHERE a MATCH 'ab*';          }
   520    523   do_execsql_test 8.3 { INSERT INTO ft10(ft10) VALUES('rebuild');        }
   521    524   do_execsql_test 8.4 { SELECT rowid FROM ft10 WHERE a MATCH 'ab*';      } {1 2 3}
   522    525   do_execsql_test 8.5 { SELECT rowid FROM ft10 WHERE b MATCH 'abav*';    } {3}
   523    526   do_execsql_test 8.6 { SELECT rowid FROM ft10 WHERE ft10 MATCH 'abas*'; } {1}
          527  +
          528  +#-------------------------------------------------------------------------
          529  +# Test cases 9.*
          530  +# 
          531  +reset_db
          532  +register_echo_module [sqlite3_connection_pointer db]
          533  +
          534  +do_execsql_test 9.1 {
          535  +  CREATE TABLE tbl1(a, b);
          536  +  INSERT INTO tbl1 VALUES('a b', 'c d');
          537  +  INSERT INTO tbl1 VALUES('e f', 'a b');
          538  +  CREATE VIRTUAL TABLE e1 USING echo(tbl1);
          539  +  CREATE VIRTUAL TABLE ft1 USING fts4(content=e1);
          540  +  INSERT INTO ft1(ft1) VALUES('rebuild');
          541  +}
          542  +
          543  +do_execsql_test 9.2 {
          544  +  SELECT rowid, * FROM ft1 WHERE ft1 MATCH 'e'
          545  +} {2 {e f} {a b}}
          546  +
          547  +do_execsql_test 9.3 {
          548  +  SELECT rowid, * FROM ft1 WHERE ft1 MATCH 'a'
          549  +} {1 {a b} {c d} 2 {e f} {a b}}
          550  +
          551  +do_execsql_test 9.4 { 
          552  +  DELETE FROM ft1 WHERE docid=1;
          553  +}
          554  +
          555  +do_execsql_test 9.5 {
          556  +  SELECT rowid, * FROM ft1 WHERE ft1 MATCH 'a'
          557  +} {2 {e f} {a b}}
          558  +
          559  +do_execsql_test 9.6 {
          560  +  INSERT INTO ft1(ft1) VALUES('rebuild');
          561  +  SELECT rowid, * FROM ft1 WHERE ft1 MATCH 'a'
          562  +} {1 {a b} {c d} 2 {e f} {a b}}
          563  +
          564  +#-------------------------------------------------------------------------
          565  +# Test cases 11.*
          566  +# 
          567  +reset_db
          568  +
          569  +do_catchsql_test 11.1 {
          570  +  CREATE VIRTUAL TABLE x1 USING fts4(content=x1);
          571  +} {1 {vtable constructor called recursively: x1}}
   524    572   
   525    573   finish_test