From 88a003e28ede10154983c5d96103129b84a94a17 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 11 Dec 2008 16:17:03 +0000 Subject: [PATCH] Guard against attacks from deliberately corrupted database files. (CVS 6021) FossilOrigin-Name: da2ec96422b1f9de2e47d3b8c19ed20579742a9b --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/vdbe.c | 10 ++++------ src/vdbeaux.c | 45 +++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 55 insertions(+), 16 deletions(-) diff --git a/manifest b/manifest index 0d7021e0a4..4092193d17 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Increase\sthe\sversion\snumber\sto\s3.6.7.\s(CVS\s6020) -D 2008-12-11T13:08:16 +C Guard\sagainst\sattacks\sfrom\sdeliberately\scorrupted\sdatabase\sfiles.\s(CVS\s6021) +D 2008-12-11T16:17:04 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in f7e4c81c347b04f7b0f1c1b081a168645d7b8af7 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -194,11 +194,11 @@ F src/update.c 080889d241e4dcd1c545c8051eb6de86f4939295 F src/utf.c 1da9c832dba0fa8f865b5b902d93f420a1ee4245 F src/util.c ea62608f66f33a7e8322de83024ae37c415c0c7f F src/vacuum.c 383d6297bddc011ab04a9eed110db6eaf523e8e9 -F src/vdbe.c 3a184e2654f6018b86827e1fa8ec414f9e4daa65 +F src/vdbe.c 46eed1fc5f24500d551c6aac960f812c6145dcee F src/vdbe.h 03516f28bf5aca00a53c4dccd6c313f96adb94f6 F src/vdbeInt.h e6e80a99ce634983b7cc2498843b4d2e5540900a F src/vdbeapi.c 85c33cfbfa56249cbe627831610afafba754477d -F src/vdbeaux.c 5356c9bbac2fb0cb75b816de1d5963b26547f656 +F src/vdbeaux.c d3a785736a7dc46a3950d393008f1ee939198a48 F src/vdbeblob.c b0dcebfafedcf9c0addc7901ad98f6f986c08935 F src/vdbemem.c f9c859ac17e2e05a0f249868ce4f191f69edd31d F src/vtab.c e39e011d7443a8d574b1b9cde207a35522e6df43 @@ -664,7 +664,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e -P 0d316160fc9e24262457d330abee40f447ff909e -R d4b82cc49600a0df1f6c3ae2d356b4a1 +P 7c367515f86c36b7ec8603754b20f1c7c4a0690a +R 444a7244e9f7d54c88f06e95ece4e75e U drh -Z c2052c4867eec9cd027c15a6112f4f1d +Z 5d08690a9b2d2b8626ebdbffda6c718a diff --git a/manifest.uuid b/manifest.uuid index ae20240e38..9fed416c22 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7c367515f86c36b7ec8603754b20f1c7c4a0690a \ No newline at end of file +da2ec96422b1f9de2e47d3b8c19ed20579742a9b \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 9f2019a1fd..b806ec34c6 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -43,7 +43,7 @@ ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.798 2008/12/11 13:05:00 drh Exp $ +** $Id: vdbe.c,v 1.799 2008/12/11 16:17:04 drh Exp $ */ #include "sqliteInt.h" #include @@ -4100,7 +4100,7 @@ case OP_Clear: { */ case OP_CreateIndex: /* out2-prerelease */ case OP_CreateTable: { /* out2-prerelease */ - int pgno; + int pgno = 0; int flags; Db *pDb; assert( pOp->p1>=0 && pOp->p1nDb ); @@ -4114,10 +4114,8 @@ case OP_CreateTable: { /* out2-prerelease */ flags = BTREE_ZERODATA; } rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, flags); - if( rc==SQLITE_OK ){ - pOut->u.i = pgno; - MemSetTypeFlag(pOut, MEM_Int); - } + pOut->u.i = pgno; + MemSetTypeFlag(pOut, MEM_Int); break; } diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 1dc25131da..943817cc57 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -14,7 +14,7 @@ ** to version 2.8.7, all this code was combined into the vdbe.c source file. ** But that file was getting too big so this subroutines were split out. ** -** $Id: vdbeaux.c,v 1.426 2008/12/10 19:26:24 drh Exp $ +** $Id: vdbeaux.c,v 1.427 2008/12/11 16:17:04 drh Exp $ */ #include "sqliteInt.h" #include @@ -2384,6 +2384,9 @@ int sqlite3VdbeRecordCompare( ** pCur points at an index entry created using the OP_MakeRecord opcode. ** Read the rowid (the last field in the record) and store it in *rowid. ** Return SQLITE_OK if everything works, or an error code otherwise. +** +** pCur might be pointing to text obtained from a corrupt database file. +** So the content cannot be trusted. Do appropriate checks on the content. */ int sqlite3VdbeIdxRowid(BtCursor *pCur, i64 *rowid){ i64 nCellKey = 0; @@ -2393,10 +2396,14 @@ int sqlite3VdbeIdxRowid(BtCursor *pCur, i64 *rowid){ u32 lenRowid; /* Size of the rowid */ Mem m, v; + /* Get the size of the index entry. Only indices entries of less + ** than 2GiB are support - anything large must be database corruption */ sqlite3BtreeKeySize(pCur, &nCellKey); - if( nCellKey<=0 || nCellKey>0x7fffffff ){ + if( unlikely(nCellKey<=0 || nCellKey>0x7fffffff) ){ return SQLITE_CORRUPT_BKPT; } + + /* Read in the complete content of the index entry */ m.flags = 0; m.db = 0; m.zMalloc = 0; @@ -2404,13 +2411,47 @@ int sqlite3VdbeIdxRowid(BtCursor *pCur, i64 *rowid){ if( rc ){ return rc; } + + /* The index entry must begin with a header size */ (void)getVarint32((u8*)m.z, szHdr); + testcase( szHdr==2 ); + testcase( szHdr==m.n ); + if( unlikely(szHdr<2 || szHdr>m.n) ){ + goto idx_rowid_corruption; + } + + /* The last field of the index should be an integer - the ROWID. + ** Verify that the last entry really is an integer. */ (void)getVarint32((u8*)&m.z[szHdr-1], typeRowid); + testcase( typeRowid==1 ); + testcase( typeRowid==2 ); + testcase( typeRowid==3 ); + testcase( typeRowid==4 ); + testcase( typeRowid==5 ); + testcase( typeRowid==6 ); + testcase( typeRowid==8 ); + testcase( typeRowid==9 ); + if( unlikely(typeRowid<1 || typeRowid>9 || typeRowid==7) ){ + goto idx_rowid_corruption; + } lenRowid = sqlite3VdbeSerialTypeLen(typeRowid); + testcase( m.n-lenRowid==szHdr ); + if( unlikely(m.n-lenRowid