diff --git a/ext/recover/dbdata.c b/ext/recover/dbdata.c index b6cb26ecd3..ca6371026e 100644 --- a/ext/recover/dbdata.c +++ b/ext/recover/dbdata.c @@ -494,6 +494,15 @@ static void dbdataValue( } } +/* This macro is a copy of the MX_CELL() macro in the SQLite core. Given +** a page-size, it returns the maximum number of cells that may be present +** on the page. */ +#define DBDATA_MX_CELL(pgsz) ((pgsz-8)/6) + +/* Maximum number of fields that may appear in a single record. This is +** the "hard-limit", according to comments in sqliteLimit.h. */ +#define DBDATA_MX_FIELD 32676 + /* ** Move an sqlite_dbdata or sqlite_dbptr cursor to the next entry. */ @@ -522,6 +531,9 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){ assert( iOff+3+2<=pCsr->nPage ); pCsr->iCell = pTab->bPtr ? -2 : 0; pCsr->nCell = get_uint16(&pCsr->aPage[iOff+3]); + if( pCsr->nCell>DBDATA_MX_CELL(pCsr->nPage) ){ + pCsr->nCell = DBDATA_MX_CELL(pCsr->nPage); + } } if( pTab->bPtr ){ @@ -566,19 +578,19 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){ if( pCsr->iCell>=pCsr->nCell ){ bNextPage = 1; }else{ + int iCellPtr = iOff + 8 + nPointer + pCsr->iCell*2; - iOff += 8 + nPointer + pCsr->iCell*2; - if( iOff>pCsr->nPage ){ + if( iCellPtr>pCsr->nPage ){ bNextPage = 1; }else{ - iOff = get_uint16(&pCsr->aPage[iOff]); + iOff = get_uint16(&pCsr->aPage[iCellPtr]); } /* 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 ){ + if( bNextPage || iOff>pCsr->nPage || iOff<=iCellPtr ){ bNextPage = 1; }else{ iOff += dbdataGetVarintU32(&pCsr->aPage[iOff], &nPayload); @@ -661,7 +673,9 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){ pCsr->iField++; if( pCsr->iField>0 ){ sqlite3_int64 iType; - if( pCsr->pHdrPtr>&pCsr->pRec[pCsr->nRec] ){ + if( pCsr->pHdrPtr>=&pCsr->pRec[pCsr->nRec] + || pCsr->iField>=DBDATA_MX_FIELD + ){ bNextPage = 1; }else{ int szField = 0; diff --git a/ext/recover/recovercorrupt2.test b/ext/recover/recovercorrupt2.test index 29acc27a35..6c216308f0 100644 --- a/ext/recover/recovercorrupt2.test +++ b/ext/recover/recovercorrupt2.test @@ -524,5 +524,33 @@ do_test 7.1 { list [catch { $R finish } msg] $msg } {1 {file is not a database}} +reset_db +breakpoint +do_test 8.0 { + sqlite3 db {} + db deserialize [decode_hexdb { +| size 8192 pagesize 4096 filename db.sqlite +| page 1 offset 0 +| 0: ac ae b3 76 74 65 20 66 6f 72 6d 61 74 20 33 00 ...vte format 3. +| 16: 10 00 01 01 00 40 20 20 00 00 00 01 00 00 00 02 .....@ ........ +| 32: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 04 ................ +| 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ................ +| 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 ................ +| 96: 00 2e 76 8a 0d ff ff ff 1e 0f cb 00 0f cb 00 00 ..v............. +| 4032: 00 00 00 00 00 00 00 00 00 00 00 33 01 06 17 19 ...........3.... +| 4048: 19 01 43 74 61 62 6c 65 54 61 62 6c 65 30 54 61 ..CtableTable0Ta +| 4064: 62 6c 65 30 02 43 52 45 41 54 45 20 54 41 42 4c ble0.CREATE TABL +| 4080: 45 20 54 61 62 6c 65 30 20 28 43 6f 6c 30 20 29 E Table0 (Col0 ) +| page 2 offset 4096 +| 0: 0d 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 ................ +| end db.sqlite +}]} {} + +do_test 8.1 { + set R [sqlite3_recover_init db main test.db2] + catch { $R run } + list [catch { $R finish } msg] $msg +} {0 {}} + finish_test diff --git a/ext/recover/sqlite3recover.c b/ext/recover/sqlite3recover.c index c445c51793..1d858c0ab9 100644 --- a/ext/recover/sqlite3recover.c +++ b/ext/recover/sqlite3recover.c @@ -1189,7 +1189,7 @@ static int recoverWriteSchema1(sqlite3_recover *p){ if( bTable && !bVirtual ){ if( SQLITE_ROW==sqlite3_step(pTblname) ){ const char *zTbl = (const char*)sqlite3_column_text(pTblname, 0); - recoverAddTable(p, zTbl, iRoot); + if( zTbl ) recoverAddTable(p, zTbl, iRoot); } recoverReset(p, pTblname); } diff --git a/manifest b/manifest index 8197099293..0fa7d973a9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C The\sread-only\sCHECK-constraint\soptimization\sof\s[34ddf02d3d21151b]\sinhibits\sthe\nxfer\soptimization\sfor\stables\swith\sCHECK\sconstraints.\s\sHowever,\sthe\sxfer\noptimization\sis\srequired\sfor\scorrect\soperation\sof\sVACUUM\sINTO\son\stables\sthat\ncontain\sgenerated\scolumns.\sFix\sthis\sby\signoring\sCHECK\sconstraints\swhen\nqualifying\sthe\sxfer\soptimization\swhile\srunning\sVACUUM.\s\sProblem\sreported\sby\n[forum:/forumpost/3ec177d68fe7fa2c|forum\spost\s3ec177d68fe7fa2c]. -D 2024-04-09T13:57:27.143 +C Avoid\ssome\sperformance\sproblems\sin\sthe\srecover\sextension\swhen\srecovering\sstrategically\scorrupted\sdatabases. +D 2024-04-09T15:09:54.458 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -478,13 +478,13 @@ F ext/rbu/rbuvacuum4.test ffccd22f67e2d0b380d2889685742159dfe0d19a3880ca3d2d1d69 F ext/rbu/sqlite3rbu.c 4a3376c0fb9a844a799ac529fb81260523f6b13c9f629bc270c632dbae5fc1f8 F ext/rbu/sqlite3rbu.h 9d923eb135c5d04aa6afd7c39ca47b0d1d0707c100e02f19fdde6a494e414304 F ext/rbu/test_rbu.c ee6ede75147bc081fe9bc3931e6b206277418d14d3fbceea6fdc6216d9b47055 -F ext/recover/dbdata.c b7746c2ec801b453840831311be4b31f8c8f9dd97791060a69bbf12392c78949 +F ext/recover/dbdata.c d2e00d3cac74319c9c6def2e56ab2146b4f4ba5d820ab275e8da24e9766c247e F ext/recover/recover1.test c484d01502239f11b61f23c1cee9f5dd19fa17617f8974e42e74d64639c524cf F ext/recover/recover_common.tcl a61306c1eb45c0c3fc45652c35b2d4ec19729e340bdf65a272ce4c229cefd85a F ext/recover/recoverbuild.test c74170e0f7b02456af41838afeb5353fdb985a48cc2331d661bbabbca7c6b8e3 F ext/recover/recoverclobber.test 3ba6c0c373c5c63d17e82eced64c05c57ccaf26c1abe1ca7141334022a79f32e F ext/recover/recovercorrupt.test 64c081ad1200ae77b447da99eb724785d6bf71715f394543dc7689642e92bf49 -F ext/recover/recovercorrupt2.test b9b974f006340a1300b5a7e687bd6097c5238498181c6f92d87406a77ece430b +F ext/recover/recovercorrupt2.test 1418f1710debc24ff38276cedfcea234beb37a34205708e7e3e6d76cc4a979db F ext/recover/recoverfault.test 9d9f88eeb222615a25e7514f234c950d46bee20d24cd8db49d8fff8d650dcfe1 F ext/recover/recoverfault2.test 730e7371bcda769554d15460cb23126abba1be8eca9539ccabf63623e7bb7e09 F ext/recover/recoverold.test 68db3d6f85dd2b98e785b6c4da4f5eea4bbe52ccf6674d9a94c7506dc92596aa @@ -492,7 +492,7 @@ F ext/recover/recoverpgsz.test 3658ab8e68475b1bb87d6af88baa04551c84b73280a566a1b F ext/recover/recoverrowid.test f948bf4024a5f41b0e21b8af80c60564c5b5d78c05a8d64fc00787715ff9f45f F ext/recover/recoverslowidx.test 5205a9742dd9490ee99950dabb622307355ef1662dea6a3a21030057bfd81411 F ext/recover/recoversql.test e66d01f95302a223bcd3fd42b5ee58dc2b53d70afa90b0d00e41e4b8eab20486 -F ext/recover/sqlite3recover.c e6eb20c469bcdb96f297f2241860bccabf9f036bfa7f3d47bcc6ca1191b108dc +F ext/recover/sqlite3recover.c 65ef0f56301a16c0536c9839fb7e23540c9c4f75da0afe3b7b4d163c8f624404 F ext/recover/sqlite3recover.h 011c799f02deb70ab685916f6f538e6bb32c4e0025e79bfd0e24ff9c74820959 F ext/recover/test_recover.c fd871a40f2238022bedcbdf3cb493b91225edaa94d6ae8892af97a10e7ccc4ba F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15 @@ -2184,8 +2184,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P c02956cd5cbf87027ba201b5d273e0efd429836ee6cabdc2f6d5b8096c876b7b -R 14ee2c4095f13f5f59e64d6dfae705ab -U drh -Z 40f988c61dc13a84e5a7ab5ecd628e6c +P a6e26e778812c8409fca77183e24d3b70189c4d02fce10c7e74cd4ccc8c8ea97 +R b9c21ffc9d4065568ea5ca672bfa94a1 +U dan +Z a2100870dc1c15edbdbfdff1cdb0d2d0 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 3f94593291..e73f4c80e2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a6e26e778812c8409fca77183e24d3b70189c4d02fce10c7e74cd4ccc8c8ea97 \ No newline at end of file +e66a834bbab9d71e02b70588ad4c71eae2e13b50e299b0269d488402bc4a7fc5 \ No newline at end of file