/ Check-in [89b8c377]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Avoid calling sqlite3BtreeEnter() in a corner case where the corresponding database handle mutex (sqlite3.mutex) may not be held. This prevents a potential deadlock or crash that can occur if the backup API, shared-cache mode and SQLITE_HAVE_CODEC are all in use.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 89b8c377a6f03d9fa885f3f94c1f0b1eec263dea
User & Date: dan 2012-09-28 20:23:42
Context
2012-09-29
14:45
Fix compiler warnings found on Lion. check-in: fd74d3d9 user: drh tags: trunk
2012-09-28
20:23
Avoid calling sqlite3BtreeEnter() in a corner case where the corresponding database handle mutex (sqlite3.mutex) may not be held. This prevents a potential deadlock or crash that can occur if the backup API, shared-cache mode and SQLITE_HAVE_CODEC are all in use. check-in: 89b8c377 user: dan tags: trunk
18:13
Modify the clearCell function to use SQLITE_CORRUPT_BKPT in the one place it was not. check-in: 472beb30 user: mistachkin tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/backup.c.

   215    215   static int backupOnePage(sqlite3_backup *p, Pgno iSrcPg, const u8 *zSrcData){
   216    216     Pager * const pDestPager = sqlite3BtreePager(p->pDest);
   217    217     const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc);
   218    218     int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest);
   219    219     const int nCopy = MIN(nSrcPgsz, nDestPgsz);
   220    220     const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz;
   221    221   #ifdef SQLITE_HAS_CODEC
   222         -  int nSrcReserve = sqlite3BtreeGetReserve(p->pSrc);
          222  +  /* Use BtreeGetReserveNoMutex() for the source b-tree, as although it is
          223  +  ** guaranteed that the shared-mutex is held by this thread, handle
          224  +  ** p->pSrc may not actually be the owner.  */
          225  +  int nSrcReserve = sqlite3BtreeGetReserveNoMutex(p->pSrc);
   223    226     int nDestReserve = sqlite3BtreeGetReserve(p->pDest);
   224    227   #endif
   225         -
   226    228     int rc = SQLITE_OK;
   227    229     i64 iOff;
   228    230   
          231  +  assert( sqlite3BtreeGetReserveNoMutex(p->pSrc)>=0 );
   229    232     assert( p->bDestLocked );
   230    233     assert( !isFatalError(p->rc) );
   231    234     assert( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) );
   232    235     assert( zSrcData );
   233    236   
   234    237     /* Catch the case where the destination is an in-memory database and the
   235    238     ** page sizes of the source and destination differ. 

Changes to src/btree.c.

  2195   2195   
  2196   2196   /*
  2197   2197   ** Return the currently defined page size
  2198   2198   */
  2199   2199   int sqlite3BtreeGetPageSize(Btree *p){
  2200   2200     return p->pBt->pageSize;
  2201   2201   }
         2202  +
         2203  +/*
         2204  +** This function is similar to sqlite3BtreeGetReserve(), except that it
         2205  +** may only be called if it is guaranteed that the b-tree mutex is already
         2206  +** held.
         2207  +**
         2208  +** This is useful in one special case in the backup API code where it is
         2209  +** known that the shared b-tree mutex is held, but the mutex on the 
         2210  +** database handle that owns *p is not. In this case if sqlite3BtreeEnter()
         2211  +** were to be called, it might collide with some other operation on the
         2212  +** database handle that owns *p, causing undefined behaviour.
         2213  +*/
         2214  +int sqlite3BtreeGetReserveNoMutex(Btree *p){
         2215  +  assert( sqlite3_mutex_held(p->pBt->mutex) );
         2216  +  return p->pBt->pageSize - p->pBt->usableSize;
         2217  +}
  2202   2218   
  2203   2219   #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM)
  2204   2220   /*
  2205   2221   ** Return the number of bytes of space at the end of every page that
  2206   2222   ** are intentually left unused.  This is the "reserved" space that is
  2207   2223   ** sometimes used by extensions.
  2208   2224   */

Changes to src/btree.h.

    67     67   int sqlite3BtreeSyncDisabled(Btree*);
    68     68   int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix);
    69     69   int sqlite3BtreeGetPageSize(Btree*);
    70     70   int sqlite3BtreeMaxPageCount(Btree*,int);
    71     71   u32 sqlite3BtreeLastPage(Btree*);
    72     72   int sqlite3BtreeSecureDelete(Btree*,int);
    73     73   int sqlite3BtreeGetReserve(Btree*);
           74  +int sqlite3BtreeGetReserveNoMutex(Btree *p);
    74     75   int sqlite3BtreeSetAutoVacuum(Btree *, int);
    75     76   int sqlite3BtreeGetAutoVacuum(Btree *);
    76     77   int sqlite3BtreeBeginTrans(Btree*,int);
    77     78   int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster);
    78     79   int sqlite3BtreeCommitPhaseTwo(Btree*, int);
    79     80   int sqlite3BtreeCommit(Btree*);
    80     81   int sqlite3BtreeRollback(Btree*,int);