Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Do not allow virtual table constructors to be called recursively. Cherrypick of [0a72726da215] |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | branch-3.8.6 |
Files: | files | file ages | folders |
SHA1: |
023a29baf0de7e4d2e7a7b5bc184bbad |
User & Date: | dan 2015-05-20 19:50:57.913 |
Context
2015-05-20
| ||
19:53 | Detect and report oversized records constructed from multiple zeroblobs. Cherrypick of [9e139afd9211]. (check-in: 4a08f6b8bb user: dan tags: branch-3.8.6) | |
19:50 | Do not allow virtual table constructors to be called recursively. Cherrypick of [0a72726da215] (check-in: 023a29baf0 user: dan tags: branch-3.8.6) | |
19:48 | Avoid signed integer overflow when converting oversized in-line integer widths and precisions in printf(). Cherrypick of [c494171f77dc], [5ce4e7d7651e], [95625ef3adc3] and [8e4ac2ce2441]. (check-in: b330c7ff6f user: dan tags: branch-3.8.6) | |
2015-04-10
| ||
07:55 | Do not allow virtual table constructors to be called recursively. (check-in: 0a72726da2 user: dan tags: trunk) | |
Changes
Changes to ext/fts3/fts3.c.
︙ | ︙ | |||
1009 1010 1011 1012 1013 1014 1015 | */ static int fts3ContentColumns( sqlite3 *db, /* Database handle */ const char *zDb, /* Name of db (i.e. "main", "temp" etc.) */ const char *zTbl, /* Name of content table */ const char ***pazCol, /* OUT: Malloc'd array of column names */ int *pnCol, /* OUT: Size of array *pazCol */ | | > > > > | 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 | */ static int fts3ContentColumns( sqlite3 *db, /* Database handle */ const char *zDb, /* Name of db (i.e. "main", "temp" etc.) */ 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 */ char **pzErr /* OUT: error message */ ){ int rc = SQLITE_OK; /* Return code */ char *zSql; /* "SELECT *" statement on zTbl */ sqlite3_stmt *pStmt = 0; /* Compiled version of zSql */ zSql = sqlite3_mprintf("SELECT * FROM %Q.%Q", zDb, zTbl); if( !zSql ){ 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); if( rc==SQLITE_OK ){ const char **azCol; /* Output array */ int nStr = 0; /* Size of all column names (incl. 0x00) */ int nCol; /* Number of table columns */ |
︙ | ︙ | |||
1271 1272 1273 1274 1275 1276 1277 | sqlite3_free(zCompress); sqlite3_free(zUncompress); zCompress = 0; zUncompress = 0; if( nCol==0 ){ sqlite3_free((void*)aCol); aCol = 0; | | | 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 | sqlite3_free(zCompress); sqlite3_free(zUncompress); zCompress = 0; zUncompress = 0; if( nCol==0 ){ sqlite3_free((void*)aCol); aCol = 0; 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. */ if( rc==SQLITE_OK && zLanguageid ){ int j; for(j=0; j<nCol; j++){ if( sqlite3_stricmp(zLanguageid, aCol[j])==0 ){ |
︙ | ︙ |
Changes to src/vtab.c.
︙ | ︙ | |||
20 21 22 23 24 25 26 27 28 29 30 31 32 33 | ** this struct allocated on the stack. It is used by the implementation of ** the sqlite3_declare_vtab() and sqlite3_vtab_config() APIs, both of which ** are invoked only from within xCreate and xConnect methods. */ struct VtabCtx { VTable *pVTable; /* The virtual table being constructed */ Table *pTab; /* The Table object to which the virtual table belongs */ }; /* ** The actual function that does the work of creating a new module. ** This function implements the sqlite3_create_module() and ** sqlite3_create_module_v2() interfaces. */ | > > | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | ** this struct allocated on the stack. It is used by the implementation of ** the sqlite3_declare_vtab() and sqlite3_vtab_config() APIs, both of which ** are invoked only from within xCreate and xConnect methods. */ struct VtabCtx { VTable *pVTable; /* The virtual table being constructed */ Table *pTab; /* The Table object to which the virtual table belongs */ VtabCtx *pPrior; /* Parent context (if any) */ int bDeclared; /* True after sqlite3_declare_vtab() is called */ }; /* ** The actual function that does the work of creating a new module. ** This function implements the sqlite3_create_module() and ** sqlite3_create_module_v2() interfaces. */ |
︙ | ︙ | |||
470 471 472 473 474 475 476 | static int vtabCallConstructor( sqlite3 *db, Table *pTab, Module *pMod, int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**), char **pzErr ){ | | | > > > > > > > > > > > > | > | > | | 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 | static int vtabCallConstructor( sqlite3 *db, Table *pTab, Module *pMod, int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**), char **pzErr ){ VtabCtx sCtx; VTable *pVTable; int rc; const char *const*azArg = (const char *const*)pTab->azModuleArg; int nArg = pTab->nModuleArg; char *zErr = 0; char *zModuleName; int iDb; 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; } pVTable = sqlite3DbMallocZero(db, sizeof(VTable)); if( !pVTable ){ sqlite3DbFree(db, zModuleName); return SQLITE_NOMEM; } pVTable->db = db; pVTable->pMod = pMod; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); pTab->azModuleArg[1] = db->aDb[iDb].zName; /* Invoke the virtual table constructor */ assert( &db->pVtabCtx ); 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 = sCtx.pPrior; if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; assert( sCtx.pTab==pTab ); if( SQLITE_OK!=rc ){ if( zErr==0 ){ *pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName); }else { *pzErr = sqlite3MPrintf(db, "%s", zErr); sqlite3_free(zErr); } sqlite3DbFree(db, pVTable); }else if( ALWAYS(pVTable->pVtab) ){ /* Justification of ALWAYS(): A correct vtab constructor must allocate ** the sqlite3_vtab object if successful. */ pVTable->pVtab->pModule = pMod->pModule; pVTable->nRef = 1; if( sCtx.bDeclared==0 ){ const char *zFormat = "vtable constructor did not declare schema: %s"; *pzErr = sqlite3MPrintf(db, zFormat, pTab->zName); sqlite3VtabUnlock(pVTable); rc = SQLITE_ERROR; }else{ int iCol; /* If everything went according to plan, link the new VTable structure |
︙ | ︙ | |||
688 689 690 691 692 693 694 695 | /* ** This function is used to set the schema of a virtual table. It is only ** valid to call this function from within the xCreate() or xConnect() of a ** virtual table module. */ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ Parse *pParse; | > < | > | 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 | /* ** This function is used to set the schema of a virtual table. It is only ** valid to call this function from within the xCreate() or xConnect() of a ** 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( !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)); if( pParse==0 ){ rc = SQLITE_NOMEM; }else{ pParse->declareVtab = 1; |
︙ | ︙ | |||
722 723 724 725 726 727 728 | ){ if( !pTab->aCol ){ pTab->aCol = pParse->pNewTable->aCol; pTab->nCol = pParse->pNewTable->nCol; pParse->pNewTable->nCol = 0; pParse->pNewTable->aCol = 0; } | | | 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 | ){ if( !pTab->aCol ){ pTab->aCol = pParse->pNewTable->aCol; pTab->nCol = pParse->pNewTable->nCol; pParse->pNewTable->nCol = 0; pParse->pNewTable->aCol = 0; } pCtx->bDeclared = 1; }else{ sqlite3Error(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr); sqlite3DbFree(db, zErr); rc = SQLITE_ERROR; } pParse->declareVtab = 0; |
︙ | ︙ |
Changes to test/fts4content.test.
︙ | ︙ | |||
44 45 46 47 48 49 50 51 52 53 54 55 56 57 | # SELECT statements. # # 8.* - Test that if the content=xxx and prefix options are used together, # the 'rebuild' command still works. # # 9.* - Test using content=xxx where xxx is a virtual table. # do_execsql_test 1.1.1 { CREATE TABLE t1(a, b, c); INSERT INTO t1 VALUES('w x', 'x y', 'y z'); CREATE VIRTUAL TABLE ft1 USING fts4(content=t1); } | > > > | 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | # SELECT statements. # # 8.* - Test that if the content=xxx and prefix options are used together, # the 'rebuild' command still works. # # 9.* - Test using content=xxx where xxx is a virtual table. # # 11.* - Test that circular references (e.g. "t1(content=t1)") are # detected. # do_execsql_test 1.1.1 { CREATE TABLE t1(a, b, c); INSERT INTO t1 VALUES('w x', 'x y', 'y z'); CREATE VIRTUAL TABLE ft1 USING fts4(content=t1); } |
︙ | ︙ | |||
402 403 404 405 406 407 408 | } #------------------------------------------------------------------------- # Test cases 6.* test # do_catchsql_test 6.1.1 { CREATE VIRTUAL TABLE ft7 USING fts4(content=t7); | | | 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 | } #------------------------------------------------------------------------- # Test cases 6.* test # do_catchsql_test 6.1.1 { CREATE VIRTUAL TABLE ft7 USING fts4(content=t7); } {1 {no such table: main.t7}} do_execsql_test 6.2.1 { CREATE TABLE t7(one, two); CREATE VIRTUAL TABLE ft7 USING fts4(content=t7); INSERT INTO t7 VALUES('A B', 'B A'); INSERT INTO t7 VALUES('C D', 'A A'); SELECT * FROM ft7; |
︙ | ︙ | |||
429 430 431 432 433 434 435 | SELECT name FROM sqlite_master WHERE name LIKE '%t7%' } { ft7 ft7_segments ft7_segdir sqlite_autoindex_ft7_segdir_1 ft7_docsize ft7_stat } do_catchsql_test 6.2.4 { SELECT * FROM ft7; | | | 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 | SELECT name FROM sqlite_master WHERE name LIKE '%t7%' } { ft7 ft7_segments ft7_segdir sqlite_autoindex_ft7_segdir_1 ft7_docsize ft7_stat } do_catchsql_test 6.2.4 { SELECT * FROM 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'); INSERT INTO t7 VALUES('C D', 'A A'); SELECT * FROM ft7; } { {A B} {B A} {C D} {A A} |
︙ | ︙ | |||
617 618 619 620 621 622 623 624 625 | do_execsql_test 10.6 { DELETE FROM ft WHERE docid=2 } do_execsql_test 10.7 { SELECT snippet(ft, '[', ']', '...', -1, 5) FROM ft WHERE ft MATCH 'e' } { {...c d [e] f g...} } finish_test | > > > > > > > > > > > | 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 | do_execsql_test 10.6 { DELETE FROM ft WHERE docid=2 } do_execsql_test 10.7 { SELECT snippet(ft, '[', ']', '...', -1, 5) FROM ft WHERE ft MATCH 'e' } { {...c d [e] f g...} } #------------------------------------------------------------------------- # 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 |