SQLite

Check-in [2594f01c73]
Login

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

Overview
Comment:Avoid leaving a suspect page in the page-cache if an error occurs during sqlite3PagerAcquire(). (CVS 6922)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 2594f01c73301f9432be9d007a079a19a3d383f9
User & Date: danielk1977 2009-07-22 16:41:15.000
Context
2009-07-22
18:07
Simplifications to btree.c in support of coverage testing. (CVS 6923) (check-in: 375fd6f9c5 user: drh tags: trunk)
16:41
Avoid leaving a suspect page in the page-cache if an error occurs during sqlite3PagerAcquire(). (CVS 6922) (check-in: 2594f01c73 user: danielk1977 tags: trunk)
14:08
Fix a double-free that can occur after database corruption is detected. (CVS 6921) (check-in: 5260e8b104 user: danielk1977 tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/pager.c.
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.612 2009/07/22 13:19:20 drh Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"

/*
** Macros for troubleshooting.  Normally turned off
*/







|







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.613 2009/07/22 16:41:15 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"

/*
** Macros for troubleshooting.  Normally turned off
*/
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
  if( (sqlite3PcacheRefCount(pPager->pPCache)==0)
   && (!pPager->exclusiveMode || pPager->journalOff>0) 
  ){
    pagerUnlockAndRollback(pPager);
  }
}

/*
** Drop a page from the cache using sqlite3PcacheDrop().
**
** If this means there are now no pages with references to them, a rollback
** occurs and the lock on the database is removed.
*/
static void pagerDropPage(DbPage *pPg){
  Pager *pPager = pPg->pPager;
  sqlite3PcacheDrop(pPg);
  pagerUnlockIfUnused(pPager);
}

/*
** Acquire a reference to page number pgno in pager pPager (a page
** reference has type DbPage*). If the requested reference is 
** successfully obtained, it is copied to *ppPage and SQLITE_OK returned.
**
** If the requested page is already in the cache, it is returned. 
** Otherwise, a new page object is allocated and populated with data







<
<
<
<
<
<
<
<
<
<
<
<







3768
3769
3770
3771
3772
3773
3774












3775
3776
3777
3778
3779
3780
3781
  if( (sqlite3PcacheRefCount(pPager->pPCache)==0)
   && (!pPager->exclusiveMode || pPager->journalOff>0) 
  ){
    pagerUnlockAndRollback(pPager);
  }
}













/*
** Acquire a reference to page number pgno in pager pPager (a page
** reference has type DbPage*). If the requested reference is 
** successfully obtained, it is copied to *ppPage and SQLITE_OK returned.
**
** If the requested page is already in the cache, it is returned. 
** Otherwise, a new page object is allocated and populated with data
3867
3868
3869
3870
3871
3872
3873

3874
3875
3876
3877
3878
3879
3880
  }
  assert( (*ppPage)->pgno==pgno );
  assert( (*ppPage)->pPager==pPager || (*ppPage)->pPager==0 );

  if( (*ppPage)->pPager ){
    /* In this case the pcache already contains an initialized copy of
    ** the page. Return without further ado.  */

    PAGER_INCR(pPager->nHit);
    return SQLITE_OK;

  }else{
    /* The pager cache has created a new page. Its content needs to 
    ** be initialized.  */
    int nMax;







>







3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
  }
  assert( (*ppPage)->pgno==pgno );
  assert( (*ppPage)->pPager==pPager || (*ppPage)->pPager==0 );

  if( (*ppPage)->pPager ){
    /* In this case the pcache already contains an initialized copy of
    ** the page. Return without further ado.  */
    assert( pgno<=PAGER_MAX_PGNO && pgno!=PAGER_MJ_PGNO(pPager) );
    PAGER_INCR(pPager->nHit);
    return SQLITE_OK;

  }else{
    /* The pager cache has created a new page. Its content needs to 
    ** be initialized.  */
    int nMax;
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939

3940

3941

3942
3943
3944
3945
3946
3947
3948
        memset(pPg->pData, 0, pPager->pageSize);
      }
      IOTRACE(("ZERO %p %d\n", pPager, pgno));
    }else{
      assert( pPg->pPager==pPager );
      rc = readDbPage(pPg);
      if( rc!=SQLITE_OK ){
        pagerDropPage(pPg);
	pPg = 0;
        goto pager_acquire_err;
      }
    }
#ifdef SQLITE_CHECK_PAGES
    pPg->pageHash = pager_pagehash(pPg);
#endif
  }

  return SQLITE_OK;

pager_acquire_err:
  assert( rc!=SQLITE_OK );

  sqlite3PagerUnref(pPg);

  pagerUnlockIfUnused(pPager);

  *ppPage = 0;
  return rc;
}

/*
** Acquire a page if it is already in the in-memory cache.  Do
** not read the page from disk.  Return a pointer to the page,







<
<












>
|
>

>







3908
3909
3910
3911
3912
3913
3914


3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
        memset(pPg->pData, 0, pPager->pageSize);
      }
      IOTRACE(("ZERO %p %d\n", pPager, pgno));
    }else{
      assert( pPg->pPager==pPager );
      rc = readDbPage(pPg);
      if( rc!=SQLITE_OK ){


        goto pager_acquire_err;
      }
    }
#ifdef SQLITE_CHECK_PAGES
    pPg->pageHash = pager_pagehash(pPg);
#endif
  }

  return SQLITE_OK;

pager_acquire_err:
  assert( rc!=SQLITE_OK );
  if( pPg ){
    sqlite3PcacheDrop(pPg);
  }
  pagerUnlockIfUnused(pPager);

  *ppPage = 0;
  return rc;
}

/*
** Acquire a page if it is already in the in-memory cache.  Do
** not read the page from disk.  Return a pointer to the page,