From: dan Date: Thu, 9 May 2019 15:07:46 +0000 (+0000) Subject: Fix further buffer overreads triggered by passing corrupt records to the sqlite_dbdat... X-Git-Tag: version-3.29.0~124 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e216ae0a3e334f6ca51ca0d1d11cf07c380dd0ea;p=thirdparty%2Fsqlite.git Fix further buffer overreads triggered by passing corrupt records to the sqlite_dbdata module. FossilOrigin-Name: dbc6a9f7f67256dea96d3245e7bec145ba65d64adf322e18f1f3ac9556b4e0b6 --- diff --git a/ext/misc/dbdata.c b/ext/misc/dbdata.c index 88906513a7..4cbb96691f 100644 --- a/ext/misc/dbdata.c +++ b/ext/misc/dbdata.c @@ -495,6 +495,7 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){ int iHdr; int U, X; int nLocal; + int bNextPage = 0; switch( pCsr->aPage[iOff] ){ case 0x02: @@ -512,82 +513,104 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){ } if( pCsr->iCell>=pCsr->nCell ){ + bNextPage = 1; + }else{ + + iOff += 8 + nPointer + pCsr->iCell*2; + if( iOff>pCsr->nPage ){ + bNextPage = 1; + }else{ + iOff = get_uint16(&pCsr->aPage[iOff]); + } + + /* For an interior node cell, skip past the child-page number */ + iOff += nPointer; + + /* Load the "byte of payload including overflow" field */ + if( bNextPage || iOff>pCsr->nPage ){ + bNextPage = 1; + }else{ + iOff += dbdataGetVarint(&pCsr->aPage[iOff], &nPayload); + } + + /* If this is a leaf intkey cell, load the rowid */ + if( bHasRowid && !bNextPage && iOffnPage ){ + iOff += dbdataGetVarint(&pCsr->aPage[iOff], &pCsr->iIntkey); + } + + /* Figure out how much data to read from the local page */ + U = pCsr->nPage; + if( bHasRowid ){ + X = U-35; + }else{ + X = ((U-12)*64/255)-23; + } + if( nPayload<=X ){ + nLocal = nPayload; + }else{ + int M, K; + M = ((U-12)*32/255)-23; + K = M+((nPayload-M)%(U-4)); + if( K<=X ){ + nLocal = K; + }else{ + nLocal = M; + } + } + + if( bNextPage || nLocal+iOff>pCsr->nPage ){ + bNextPage = 1; + }else{ + + /* Allocate space for payload. And a bit more to catch small buffer + ** overruns caused by attempting to read a varint or similar from + ** near the end of a corrupt record. */ + pCsr->pRec = (u8*)sqlite3_malloc64(nPayload+100); + if( pCsr->pRec==0 ) return SQLITE_NOMEM; + memset(pCsr->pRec, 0, nPayload+100); + pCsr->nRec = nPayload; + + /* Load the nLocal bytes of payload */ + memcpy(pCsr->pRec, &pCsr->aPage[iOff], nLocal); + iOff += nLocal; + + /* Load content from overflow pages */ + if( nPayload>nLocal ){ + sqlite3_int64 nRem = nPayload - nLocal; + unsigned int pgnoOvfl = get_uint32(&pCsr->aPage[iOff]); + while( nRem>0 ){ + u8 *aOvfl = 0; + int nOvfl = 0; + int nCopy; + rc = dbdataLoadPage(pCsr, pgnoOvfl, &aOvfl, &nOvfl); + assert( rc!=SQLITE_OK || nOvfl==pCsr->nPage ); + if( rc!=SQLITE_OK ) return rc; + + nCopy = U-4; + if( nCopy>nRem ) nCopy = nRem; + memcpy(&pCsr->pRec[nPayload-nRem], &aOvfl[4], nCopy); + nRem -= nCopy; + + pgnoOvfl = get_uint32(aOvfl); + sqlite3_free(aOvfl); + } + } + + iHdr = dbdataGetVarint(pCsr->pRec, &nHdr); + pCsr->nHdr = nHdr; + pCsr->pHdrPtr = &pCsr->pRec[iHdr]; + pCsr->pPtr = &pCsr->pRec[pCsr->nHdr]; + pCsr->iField = (bHasRowid ? -1 : 0); + } + } + + if( bNextPage ){ sqlite3_free(pCsr->aPage); pCsr->aPage = 0; if( pCsr->bOnePage ) return SQLITE_OK; pCsr->iPgno++; continue; } - - iOff += 8 + nPointer + pCsr->iCell*2; - iOff = get_uint16(&pCsr->aPage[iOff]); - - /* For an interior node cell, skip past the child-page number */ - iOff += nPointer; - - /* Load the "byte of payload including overflow" field */ - iOff += dbdataGetVarint(&pCsr->aPage[iOff], &nPayload); - - /* If this is a leaf intkey cell, load the rowid */ - if( bHasRowid ){ - iOff += dbdataGetVarint(&pCsr->aPage[iOff], &pCsr->iIntkey); - } - - /* Allocate space for payload */ - pCsr->pRec = (u8*)sqlite3_malloc64(nPayload); - if( pCsr->pRec==0 ) return SQLITE_NOMEM; - pCsr->nRec = nPayload; - - U = pCsr->nPage; - if( bHasRowid ){ - X = U-35; - }else{ - X = ((U-12)*64/255)-23; - } - if( nPayload<=X ){ - nLocal = nPayload; - }else{ - int M, K; - M = ((U-12)*32/255)-23; - K = M+((nPayload-M)%(U-4)); - if( K<=X ){ - nLocal = K; - }else{ - nLocal = M; - } - } - - /* Load the nLocal bytes of payload */ - memcpy(pCsr->pRec, &pCsr->aPage[iOff], nLocal); - iOff += nLocal; - - /* Load content from overflow pages */ - if( nPayload>nLocal ){ - sqlite3_int64 nRem = nPayload - nLocal; - unsigned int pgnoOvfl = get_uint32(&pCsr->aPage[iOff]); - while( nRem>0 ){ - u8 *aOvfl = 0; - int nOvfl = 0; - int nCopy; - rc = dbdataLoadPage(pCsr, pgnoOvfl, &aOvfl, &nOvfl); - assert( rc!=SQLITE_OK || nOvfl==pCsr->nPage ); - if( rc!=SQLITE_OK ) return rc; - - nCopy = U-4; - if( nCopy>nRem ) nCopy = nRem; - memcpy(&pCsr->pRec[nPayload-nRem], &aOvfl[4], nCopy); - nRem -= nCopy; - - pgnoOvfl = get_uint32(aOvfl); - sqlite3_free(aOvfl); - } - } - - iHdr = dbdataGetVarint(pCsr->pRec, &nHdr); - pCsr->nHdr = nHdr; - pCsr->pHdrPtr = &pCsr->pRec[iHdr]; - pCsr->pPtr = &pCsr->pRec[pCsr->nHdr]; - pCsr->iField = (bHasRowid ? -1 : 0); }else{ pCsr->iField++; if( pCsr->iField>0 ){ diff --git a/manifest b/manifest index 4b83c71c58..83937eb82e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Have\s".recover"\shandle\scases\swhere\sthe\ssqlite_master\stable\scontains\smalformed\sSQL\sstatements. -D 2019-05-09T14:15:19.691 +C Fix\sfurther\sbuffer\soverreads\striggered\sby\spassing\scorrupt\srecords\sto\sthe\ssqlite_dbdata\smodule. +D 2019-05-09T15:07:46.363 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -284,7 +284,7 @@ F ext/misc/closure.c dbfd8543b2a017ae6b1a5843986b22ddf99ff126ec9634a2f4047cd14c8 F ext/misc/completion.c cec672d40604075bb341a7f11ac48393efdcd90a979269b8fe7977ea62d0547f F ext/misc/compress.c dd4f8a6d0baccff3c694757db5b430f3bbd821d8686d1fc24df55cf9f035b189 F ext/misc/csv.c 7f047aeb68f5802e7ce6639292095d622a488bb43526ed04810e0649faa71ceb -F ext/misc/dbdata.c 1d3d1ebd23d3e4e5debbc54719376781e146626c2ee0b989b412b1a9c8ccdd37 +F ext/misc/dbdata.c db2674c3a5913a784a75a11d1e7905b14f6b81de1879d6e5fde4f0887f08decf F ext/misc/dbdump.c baf6e37447c9d6968417b1cd34cbedb0b0ab3f91b5329501d8a8d5be3287c336 F ext/misc/eval.c 4b4757592d00fd32e44c7a067e6a0e4839c81a4d57abc4131ee7806d1be3104e F ext/misc/explain.c d5c12962d79913ef774b297006872af1fccda388f61a11d37758f9179a09551f @@ -1825,7 +1825,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 47fa65343e46c7782a173174952c637c5621e16229ece258dc7e7a556683ca0c -R be79b692a16f80cd3224bf9c098d5fd5 +P e736da9c18fad138c5502d354c3553373cba15358b69e44b257f60def59422e2 +R 32f00eab291c2d8cfb2d8bb909898960 U dan -Z 9d48ce941293959626321b38e8342e0f +Z f672687cf39d09ecc13e261b2e491ea1 diff --git a/manifest.uuid b/manifest.uuid index 5faf9c5ba6..85b050179e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e736da9c18fad138c5502d354c3553373cba15358b69e44b257f60def59422e2 \ No newline at end of file +dbc6a9f7f67256dea96d3245e7bec145ba65d64adf322e18f1f3ac9556b4e0b6 \ No newline at end of file