/ Check-in [dbc6a9f7]
Login

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

Overview
Comment:Fix further buffer overreads triggered by passing corrupt records to the sqlite_dbdata module.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: dbc6a9f7f67256dea96d3245e7bec145ba65d64adf322e18f1f3ac9556b4e0b6
User & Date: dan 2019-05-09 15:07:46
Context
2019-05-09
15:51
Fix another corruption related buffer overread in the sqlite_dbdata module. check-in: 5cd728fb user: dan tags: trunk
15:07
Fix further buffer overreads triggered by passing corrupt records to the sqlite_dbdata module. check-in: dbc6a9f7 user: dan tags: trunk
14:15
Have ".recover" handle cases where the sqlite_master table contains malformed SQL statements. check-in: e736da9c user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/misc/dbdata.c.

   491    491           int bHasRowid = 0;
   492    492           int nPointer = 0;
   493    493           sqlite3_int64 nPayload = 0;
   494    494           sqlite3_int64 nHdr = 0;
   495    495           int iHdr;
   496    496           int U, X;
   497    497           int nLocal;
          498  +        int bNextPage = 0;
   498    499     
   499    500           switch( pCsr->aPage[iOff] ){
   500    501             case 0x02:
   501    502               nPointer = 4;
   502    503               break;
   503    504             case 0x0a:
   504    505               break;
................................................................................
   508    509             default:
   509    510               /* This is not a b-tree page with records on it. Continue. */
   510    511               pCsr->iCell = pCsr->nCell;
   511    512               break;
   512    513           }
   513    514   
   514    515           if( pCsr->iCell>=pCsr->nCell ){
          516  +          bNextPage = 1;
          517  +        }else{
          518  +  
          519  +          iOff += 8 + nPointer + pCsr->iCell*2;
          520  +          if( iOff>pCsr->nPage ){
          521  +            bNextPage = 1;
          522  +          }else{
          523  +            iOff = get_uint16(&pCsr->aPage[iOff]);
          524  +          }
          525  +    
          526  +          /* For an interior node cell, skip past the child-page number */
          527  +          iOff += nPointer;
          528  +    
          529  +          /* Load the "byte of payload including overflow" field */
          530  +          if( bNextPage || iOff>pCsr->nPage ){
          531  +            bNextPage = 1;
          532  +          }else{
          533  +            iOff += dbdataGetVarint(&pCsr->aPage[iOff], &nPayload);
          534  +          }
          535  +    
          536  +          /* If this is a leaf intkey cell, load the rowid */
          537  +          if( bHasRowid && !bNextPage && iOff<pCsr->nPage ){
          538  +            iOff += dbdataGetVarint(&pCsr->aPage[iOff], &pCsr->iIntkey);
          539  +          }
          540  +    
          541  +          /* Figure out how much data to read from the local page */
          542  +          U = pCsr->nPage;
          543  +          if( bHasRowid ){
          544  +            X = U-35;
          545  +          }else{
          546  +            X = ((U-12)*64/255)-23;
          547  +          }
          548  +          if( nPayload<=X ){
          549  +            nLocal = nPayload;
          550  +          }else{
          551  +            int M, K;
          552  +            M = ((U-12)*32/255)-23;
          553  +            K = M+((nPayload-M)%(U-4));
          554  +            if( K<=X ){
          555  +              nLocal = K;
          556  +            }else{
          557  +              nLocal = M;
          558  +            }
          559  +          }
          560  +
          561  +          if( bNextPage || nLocal+iOff>pCsr->nPage ){
          562  +            bNextPage = 1;
          563  +          }else{
          564  +
          565  +            /* Allocate space for payload. And a bit more to catch small buffer
          566  +            ** overruns caused by attempting to read a varint or similar from 
          567  +            ** near the end of a corrupt record.  */
          568  +            pCsr->pRec = (u8*)sqlite3_malloc64(nPayload+100);
          569  +            if( pCsr->pRec==0 ) return SQLITE_NOMEM;
          570  +            memset(pCsr->pRec, 0, nPayload+100);
          571  +            pCsr->nRec = nPayload;
          572  +
          573  +            /* Load the nLocal bytes of payload */
          574  +            memcpy(pCsr->pRec, &pCsr->aPage[iOff], nLocal);
          575  +            iOff += nLocal;
          576  +
          577  +            /* Load content from overflow pages */
          578  +            if( nPayload>nLocal ){
          579  +              sqlite3_int64 nRem = nPayload - nLocal;
          580  +              unsigned int pgnoOvfl = get_uint32(&pCsr->aPage[iOff]);
          581  +              while( nRem>0 ){
          582  +                u8 *aOvfl = 0;
          583  +                int nOvfl = 0;
          584  +                int nCopy;
          585  +                rc = dbdataLoadPage(pCsr, pgnoOvfl, &aOvfl, &nOvfl);
          586  +                assert( rc!=SQLITE_OK || nOvfl==pCsr->nPage );
          587  +                if( rc!=SQLITE_OK ) return rc;
          588  +
          589  +                nCopy = U-4;
          590  +                if( nCopy>nRem ) nCopy = nRem;
          591  +                memcpy(&pCsr->pRec[nPayload-nRem], &aOvfl[4], nCopy);
          592  +                nRem -= nCopy;
          593  +
          594  +                pgnoOvfl = get_uint32(aOvfl);
          595  +                sqlite3_free(aOvfl);
          596  +              }
          597  +            }
          598  +    
          599  +            iHdr = dbdataGetVarint(pCsr->pRec, &nHdr);
          600  +            pCsr->nHdr = nHdr;
          601  +            pCsr->pHdrPtr = &pCsr->pRec[iHdr];
          602  +            pCsr->pPtr = &pCsr->pRec[pCsr->nHdr];
          603  +            pCsr->iField = (bHasRowid ? -1 : 0);
          604  +          }
          605  +        }
          606  +
          607  +        if( bNextPage ){
   515    608             sqlite3_free(pCsr->aPage);
   516    609             pCsr->aPage = 0;
   517    610             if( pCsr->bOnePage ) return SQLITE_OK;
   518    611             pCsr->iPgno++;
   519    612             continue;
   520    613           }
   521         -  
   522         -        iOff += 8 + nPointer + pCsr->iCell*2;
   523         -        iOff = get_uint16(&pCsr->aPage[iOff]);
   524         -  
   525         -        /* For an interior node cell, skip past the child-page number */
   526         -        iOff += nPointer;
   527         -  
   528         -        /* Load the "byte of payload including overflow" field */
   529         -        iOff += dbdataGetVarint(&pCsr->aPage[iOff], &nPayload);
   530         -  
   531         -        /* If this is a leaf intkey cell, load the rowid */
   532         -        if( bHasRowid ){
   533         -          iOff += dbdataGetVarint(&pCsr->aPage[iOff], &pCsr->iIntkey);
   534         -        }
   535         -  
   536         -        /* Allocate space for payload */
   537         -        pCsr->pRec = (u8*)sqlite3_malloc64(nPayload);
   538         -        if( pCsr->pRec==0 ) return SQLITE_NOMEM;
   539         -        pCsr->nRec = nPayload;
   540         -  
   541         -        U = pCsr->nPage;
   542         -        if( bHasRowid ){
   543         -          X = U-35;
   544         -        }else{
   545         -          X = ((U-12)*64/255)-23;
   546         -        }
   547         -        if( nPayload<=X ){
   548         -          nLocal = nPayload;
   549         -        }else{
   550         -          int M, K;
   551         -          M = ((U-12)*32/255)-23;
   552         -          K = M+((nPayload-M)%(U-4));
   553         -          if( K<=X ){
   554         -            nLocal = K;
   555         -          }else{
   556         -            nLocal = M;
   557         -          }
   558         -        }
   559         -  
   560         -        /* Load the nLocal bytes of payload */
   561         -        memcpy(pCsr->pRec, &pCsr->aPage[iOff], nLocal);
   562         -        iOff += nLocal;
   563         -  
   564         -        /* Load content from overflow pages */
   565         -        if( nPayload>nLocal ){
   566         -          sqlite3_int64 nRem = nPayload - nLocal;
   567         -          unsigned int pgnoOvfl = get_uint32(&pCsr->aPage[iOff]);
   568         -          while( nRem>0 ){
   569         -            u8 *aOvfl = 0;
   570         -            int nOvfl = 0;
   571         -            int nCopy;
   572         -            rc = dbdataLoadPage(pCsr, pgnoOvfl, &aOvfl, &nOvfl);
   573         -            assert( rc!=SQLITE_OK || nOvfl==pCsr->nPage );
   574         -            if( rc!=SQLITE_OK ) return rc;
   575         -  
   576         -            nCopy = U-4;
   577         -            if( nCopy>nRem ) nCopy = nRem;
   578         -            memcpy(&pCsr->pRec[nPayload-nRem], &aOvfl[4], nCopy);
   579         -            nRem -= nCopy;
   580         -  
   581         -            pgnoOvfl = get_uint32(aOvfl);
   582         -            sqlite3_free(aOvfl);
   583         -          }
   584         -        }
   585         -  
   586         -        iHdr = dbdataGetVarint(pCsr->pRec, &nHdr);
   587         -        pCsr->nHdr = nHdr;
   588         -        pCsr->pHdrPtr = &pCsr->pRec[iHdr];
   589         -        pCsr->pPtr = &pCsr->pRec[pCsr->nHdr];
   590         -        pCsr->iField = (bHasRowid ? -1 : 0);
   591    614         }else{
   592    615           pCsr->iField++;
   593    616           if( pCsr->iField>0 ){
   594    617             sqlite3_int64 iType;
   595    618             pCsr->pHdrPtr += dbdataGetVarint(pCsr->pHdrPtr, &iType);
   596    619             pCsr->pPtr += dbdataValueBytes(iType);
   597    620           }