Index: src/pager.c ================================================================== --- src/pager.c +++ src/pager.c @@ -5374,11 +5374,15 @@ assert( pPager->hasHeldSharedLock==1 ); pBase = sqlite3PcacheFetch(pPager->pPCache, pgno, 3); if( pBase==0 ){ pPg = 0; - rc = sqlite3PcacheFetchStress(pPager->pPCache, pgno, &pBase); + if( pgno==0 ){ + rc = SQLITE_CORRUPT_BKPT; + }else{ + rc = sqlite3PcacheFetchStress(pPager->pPCache, pgno, &pBase); + } if( rc!=SQLITE_OK ) goto pager_acquire_err; if( pBase==0 ){ rc = SQLITE_NOMEM_BKPT; goto pager_acquire_err; } @@ -5398,15 +5402,15 @@ }else{ /* The pager cache has created a new page. Its content needs to ** be initialized. But first some error checks: ** - ** (1) Minimum page number is 1 - ** (2) The maximum page number is 2^31 - ** (3) Never try to fetch the locking page + ** (1) The maximum page number is 2^31 + ** (2) Never try to fetch the locking page */ - if( pgno==0 || pgno>PAGER_MAX_PGNO || pgno==PAGER_MJ_PGNO(pPager) ){ + assert( pgno>0 ); + if( pgno>PAGER_MAX_PGNO || pgno==PAGER_MJ_PGNO(pPager) ){ rc = SQLITE_CORRUPT_BKPT; goto pager_acquire_err; } pPg->pPager = pPager; Index: src/pcache1.c ================================================================== --- src/pcache1.c +++ src/pcache1.c @@ -995,11 +995,11 @@ if( !pPage->isPinned ){ return pcache1PinPage(pPage); }else{ return pPage; } - }else if( createFlag ){ + }else if( createFlag && iKey ){ /* Steps 3, 4, and 5 implemented by this subroutine */ return pcache1FetchStage2(pCache, iKey, createFlag); }else{ return 0; } Index: src/sqlite.h.in ================================================================== --- src/sqlite.h.in +++ src/sqlite.h.in @@ -7213,11 +7213,12 @@ ** single database page. The pExtra element of sqlite3_pcache_page will be ** a pointer to the szExtra bytes of extra storage that SQLite has requested ** for each entry in the page cache. ** ** The page to be fetched is determined by the key. ^The minimum key value -** is 1. After it has been retrieved using xFetch, the page is considered +** is 1. The xFetch() method must return NULL if passed a key of 0. +** After it has been retrieved using xFetch, the page is considered ** to be "pinned". ** ** If the requested page is already in the page cache, then the page cache ** implementation must return a pointer to the page buffer with its content ** intact. If the requested page is not already in the cache, then the @@ -7225,14 +7226,15 @@ ** parameter to help it determined what action to take: ** ** **
createFlag Behavior when page is not already in cache **
0 Do not allocate a new page. Return NULL. -**
1 Allocate a new page if it easy and convenient to do so. -** Otherwise return NULL. +**
1 Allocate a new page if it easy and convenient to do so +** and the key is not zero. Otherwise return NULL. **
2 Make every effort to allocate a new page. Only return -** NULL if allocating a new page is effectively impossible. +** NULL if the key is zero or if allocating a new page is +** effectively impossible. **
** ** ^(SQLite will normally invoke xFetch() with a createFlag of 0 or 1. SQLite ** will only use a createFlag of 2 after a prior call with a createFlag of 1 ** failed.)^ In between the to xFetch() calls, SQLite may