| Index: third_party/sqlite/src/src/backup.c
 | 
| diff --git a/third_party/sqlite/src/src/backup.c b/third_party/sqlite/src/src/backup.c
 | 
| index 1e5f108540a328fa8a1b09bb9b002b9772646ff6..db8baeac5e4f8827e1ac77435faf87e3b563a1da 100644
 | 
| --- a/third_party/sqlite/src/src/backup.c
 | 
| +++ b/third_party/sqlite/src/src/backup.c
 | 
| @@ -11,8 +11,6 @@
 | 
|  *************************************************************************
 | 
|  ** This file contains the implementation of the sqlite3_backup_XXX() 
 | 
|  ** API functions and the related features.
 | 
| -**
 | 
| -** $Id: backup.c,v 1.19 2009/07/06 19:03:13 drh Exp $
 | 
|  */
 | 
|  #include "sqliteInt.h"
 | 
|  #include "btreeInt.h"
 | 
| @@ -100,10 +98,10 @@ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
 | 
|      }else{
 | 
|        pParse->db = pDb;
 | 
|        if( sqlite3OpenTempDatabase(pParse) ){
 | 
| -        sqlite3ErrorClear(pParse);
 | 
|          sqlite3Error(pErrorDb, pParse->rc, "%s", pParse->zErrMsg);
 | 
|          rc = SQLITE_ERROR;
 | 
|        }
 | 
| +      sqlite3DbFree(pErrorDb, pParse->zErrMsg);
 | 
|        sqlite3StackFree(pErrorDb, pParse);
 | 
|      }
 | 
|      if( rc ){
 | 
| @@ -152,7 +150,10 @@ sqlite3_backup *sqlite3_backup_init(
 | 
|      );
 | 
|      p = 0;
 | 
|    }else {
 | 
| -    /* Allocate space for a new sqlite3_backup object */
 | 
| +    /* Allocate space for a new sqlite3_backup object...
 | 
| +    ** EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a
 | 
| +    ** call to sqlite3_backup_init() and is destroyed by a call to
 | 
| +    ** sqlite3_backup_finish(). */
 | 
|      p = (sqlite3_backup *)sqlite3_malloc(sizeof(sqlite3_backup));
 | 
|      if( !p ){
 | 
|        sqlite3Error(pDestDb, SQLITE_NOMEM, 0);
 | 
| @@ -219,9 +220,18 @@ static int backupOnePage(sqlite3_backup *p, Pgno iSrcPg, const u8 *zSrcData){
 | 
|    /* Catch the case where the destination is an in-memory database and the
 | 
|    ** page sizes of the source and destination differ. 
 | 
|    */
 | 
| -  if( nSrcPgsz!=nDestPgsz && sqlite3PagerIsMemdb(sqlite3BtreePager(p->pDest)) ){
 | 
| +  if( nSrcPgsz!=nDestPgsz && sqlite3PagerIsMemdb(pDestPager) ){
 | 
| +    rc = SQLITE_READONLY;
 | 
| +  }
 | 
| +
 | 
| +#ifdef SQLITE_HAS_CODEC
 | 
| +  /* Backup is not possible if the page size of the destination is changing
 | 
| +  ** a a codec is in use.
 | 
| +  */
 | 
| +  if( nSrcPgsz!=nDestPgsz && sqlite3PagerGetCodec(pDestPager)!=0 ){
 | 
|      rc = SQLITE_READONLY;
 | 
|    }
 | 
| +#endif
 | 
|  
 | 
|    /* This loop runs once for each destination page spanned by the source 
 | 
|    ** page. For each iteration, variable iOff is set to the byte offset
 | 
| @@ -289,6 +299,9 @@ static void attachBackupObject(sqlite3_backup *p){
 | 
|  */
 | 
|  int sqlite3_backup_step(sqlite3_backup *p, int nPage){
 | 
|    int rc;
 | 
| +  int destMode;       /* Destination journal mode */
 | 
| +  int pgszSrc = 0;    /* Source page size */
 | 
| +  int pgszDest = 0;   /* Destination page size */
 | 
|  
 | 
|    sqlite3_mutex_enter(p->pSrcDb->mutex);
 | 
|    sqlite3BtreeEnter(p->pSrc);
 | 
| @@ -329,13 +342,21 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
 | 
|        rc = sqlite3BtreeBeginTrans(p->pSrc, 0);
 | 
|        bCloseTrans = 1;
 | 
|      }
 | 
| +
 | 
| +    /* Do not allow backup if the destination database is in WAL mode
 | 
| +    ** and the page sizes are different between source and destination */
 | 
| +    pgszSrc = sqlite3BtreeGetPageSize(p->pSrc);
 | 
| +    pgszDest = sqlite3BtreeGetPageSize(p->pDest);
 | 
| +    destMode = sqlite3PagerGetJournalMode(sqlite3BtreePager(p->pDest));
 | 
| +    if( SQLITE_OK==rc && destMode==PAGER_JOURNALMODE_WAL && pgszSrc!=pgszDest ){
 | 
| +      rc = SQLITE_READONLY;
 | 
| +    }
 | 
|    
 | 
|      /* Now that there is a read-lock on the source database, query the
 | 
|      ** source pager for the number of pages in the database.
 | 
|      */
 | 
| -    if( rc==SQLITE_OK ){
 | 
| -      rc = sqlite3PagerPagecount(pSrcPager, &nSrcPage);
 | 
| -    }
 | 
| +    nSrcPage = (int)sqlite3BtreeLastPage(p->pSrc);
 | 
| +    assert( nSrcPage>=0 );
 | 
|      for(ii=0; (nPage<0 || ii<nPage) && p->iNext<=(Pgno)nSrcPage && !rc; ii++){
 | 
|        const Pgno iSrcPg = p->iNext;                 /* Source page number */
 | 
|        if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){
 | 
| @@ -366,8 +387,6 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
 | 
|      if( rc==SQLITE_DONE 
 | 
|       && (rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1))==SQLITE_OK
 | 
|      ){
 | 
| -      const int nSrcPagesize = sqlite3BtreeGetPageSize(p->pSrc);
 | 
| -      const int nDestPagesize = sqlite3BtreeGetPageSize(p->pDest);
 | 
|        int nDestTruncate;
 | 
|    
 | 
|        if( p->pDestDb ){
 | 
| @@ -386,18 +405,20 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
 | 
|        ** journalled by PagerCommitPhaseOne() before they are destroyed
 | 
|        ** by the file truncation.
 | 
|        */
 | 
| -      if( nSrcPagesize<nDestPagesize ){
 | 
| -        int ratio = nDestPagesize/nSrcPagesize;
 | 
| +      assert( pgszSrc==sqlite3BtreeGetPageSize(p->pSrc) );
 | 
| +      assert( pgszDest==sqlite3BtreeGetPageSize(p->pDest) );
 | 
| +      if( pgszSrc<pgszDest ){
 | 
| +        int ratio = pgszDest/pgszSrc;
 | 
|          nDestTruncate = (nSrcPage+ratio-1)/ratio;
 | 
|          if( nDestTruncate==(int)PENDING_BYTE_PAGE(p->pDest->pBt) ){
 | 
|            nDestTruncate--;
 | 
|          }
 | 
|        }else{
 | 
| -        nDestTruncate = nSrcPage * (nSrcPagesize/nDestPagesize);
 | 
| +        nDestTruncate = nSrcPage * (pgszSrc/pgszDest);
 | 
|        }
 | 
|        sqlite3PagerTruncateImage(pDestPager, nDestTruncate);
 | 
|  
 | 
| -      if( nSrcPagesize<nDestPagesize ){
 | 
| +      if( pgszSrc<pgszDest ){
 | 
|          /* If the source page-size is smaller than the destination page-size,
 | 
|          ** two extra things may need to happen:
 | 
|          **
 | 
| @@ -407,31 +428,31 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
 | 
|          **     pending-byte page in the source database may need to be
 | 
|          **     copied into the destination database.
 | 
|          */
 | 
| -        const i64 iSize = (i64)nSrcPagesize * (i64)nSrcPage;
 | 
| +        const i64 iSize = (i64)pgszSrc * (i64)nSrcPage;
 | 
|          sqlite3_file * const pFile = sqlite3PagerFile(pDestPager);
 | 
|  
 | 
|          assert( pFile );
 | 
| -        assert( (i64)nDestTruncate*(i64)nDestPagesize >= iSize || (
 | 
| +        assert( (i64)nDestTruncate*(i64)pgszDest >= iSize || (
 | 
|                nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1)
 | 
| -           && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+nDestPagesize
 | 
| +           && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest
 | 
|          ));
 | 
|          if( SQLITE_OK==(rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1))
 | 
|           && SQLITE_OK==(rc = backupTruncateFile(pFile, iSize))
 | 
|           && SQLITE_OK==(rc = sqlite3PagerSync(pDestPager))
 | 
|          ){
 | 
|            i64 iOff;
 | 
| -          i64 iEnd = MIN(PENDING_BYTE + nDestPagesize, iSize);
 | 
| +          i64 iEnd = MIN(PENDING_BYTE + pgszDest, iSize);
 | 
|            for(
 | 
| -            iOff=PENDING_BYTE+nSrcPagesize; 
 | 
| +            iOff=PENDING_BYTE+pgszSrc; 
 | 
|              rc==SQLITE_OK && iOff<iEnd; 
 | 
| -            iOff+=nSrcPagesize
 | 
| +            iOff+=pgszSrc
 | 
|            ){
 | 
|              PgHdr *pSrcPg = 0;
 | 
| -            const Pgno iSrcPg = (Pgno)((iOff/nSrcPagesize)+1);
 | 
| +            const Pgno iSrcPg = (Pgno)((iOff/pgszSrc)+1);
 | 
|              rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg);
 | 
|              if( rc==SQLITE_OK ){
 | 
|                u8 *zData = sqlite3PagerGetData(pSrcPg);
 | 
| -              rc = sqlite3OsWrite(pFile, zData, nSrcPagesize, iOff);
 | 
| +              rc = sqlite3OsWrite(pFile, zData, pgszSrc, iOff);
 | 
|              }
 | 
|              sqlite3PagerUnref(pSrcPg);
 | 
|            }
 | 
| @@ -460,6 +481,9 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
 | 
|        assert( rc2==SQLITE_OK );
 | 
|      }
 | 
|    
 | 
| +    if( rc==SQLITE_IOERR_NOMEM ){
 | 
| +      rc = SQLITE_NOMEM;
 | 
| +    }
 | 
|      p->rc = rc;
 | 
|    }
 | 
|    if( p->pDestDb ){
 | 
| @@ -512,6 +536,9 @@ int sqlite3_backup_finish(sqlite3_backup *p){
 | 
|    }
 | 
|    sqlite3BtreeLeave(p->pSrc);
 | 
|    if( p->pDestDb ){
 | 
| +    /* EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a
 | 
| +    ** call to sqlite3_backup_init() and is destroyed by a call to
 | 
| +    ** sqlite3_backup_finish(). */
 | 
|      sqlite3_free(p);
 | 
|    }
 | 
|    sqlite3_mutex_leave(mutex);
 | 
| 
 |