From: dan Date: Fri, 16 Aug 2013 14:09:43 +0000 (+0000) Subject: Avoid buffer overreads and false OOM error reports that could be caused by corrupted... X-Git-Tag: version-3.8.1~132^2~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c367d4c05207333872408cf822eafc45ab281ee7;p=thirdparty%2Fsqlite.git Avoid buffer overreads and false OOM error reports that could be caused by corrupted sample records in the sqlite_stat4 table. FossilOrigin-Name: 9f85b6a52a0b9b1524daa6f24d85257e7f591e95 --- diff --git a/manifest b/manifest index 8b743d0d4c..3c5429d527 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\spotential\ssegfault\sfollowing\san\sOOM\swhile\srunning\sANALYZE. -D 2013-08-16T13:34:50.978 +C Avoid\sbuffer\soverreads\sand\sfalse\sOOM\serror\sreports\sthat\scould\sbe\scaused\sby\scorrupted\ssample\srecords\sin\sthe\ssqlite_stat4\stable. +D 2013-08-16T14:09:43.262 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -157,7 +157,7 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad F src/alter.c 2af0330bb1b601af7a7789bf7229675fd772a083 -F src/analyze.c 0427f9ea0b74fa90fc9b372b7f4ca136b48bb6b5 +F src/analyze.c 30dd8962a6b95ed62793dc1e488ddec440c8a589 F src/attach.c 1816f5a9eea8d2010fc2b22b44f0f63eb3a62704 F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c 43b348822db3e4cef48b2ae5a445fbeb6c73a165 @@ -308,7 +308,7 @@ F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4 F test/analyze6.test 19151da2c4e918905d2081b74ac5c4d47fc850ab F test/analyze7.test bb1409afc9e8629e414387ef048b8e0e3e0bdc4f F test/analyze8.test 093d15c1c888eed5034304a98c992f7360130b88 -F test/analyze9.test b73f9514af962a139d2c61d7741b0ba090789ea2 +F test/analyze9.test baeb1ac3f2a6ee8bc740721f3e85b84f5ec35002 F test/analyzeA.test 1a5c40079894847976d983ca39c707aaa44b6944 F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b @@ -1107,7 +1107,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P c69b512af276a438399747af22659415af3a5d4d -R 1d895af259827a89f1c38733ddab2eab -U drh -Z 7fb242ddc62e8a326599f76c33fd34fe +P 0118797823c9093e68113578f3f3aae65de41453 +R be7b1ba9d391582f66fe114108e327e7 +U dan +Z daee3e03dcffd75664c2937dc08ce654 diff --git a/manifest.uuid b/manifest.uuid index acd4f03a69..82cf5035bc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0118797823c9093e68113578f3f3aae65de41453 \ No newline at end of file +9f85b6a52a0b9b1524daa6f24d85257e7f591e95 \ No newline at end of file diff --git a/src/analyze.c b/src/analyze.c index b1931914a8..421890034b 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -1411,18 +1411,25 @@ static int loadStatTbl( initAvgEq(pPrevIdx); pPrevIdx = pIdx; } - pSample = &pIdx->aSample[pIdx->nSample++]; + pSample = &pIdx->aSample[pIdx->nSample]; decodeIntArray((char*)sqlite3_column_text(pStmt,1), nCol, pSample->anEq, 0); decodeIntArray((char*)sqlite3_column_text(pStmt,2), nCol, pSample->anLt, 0); decodeIntArray((char*)sqlite3_column_text(pStmt,3), nCol, pSample->anDLt,0); + /* Take a copy of the sample. Add two 0x00 bytes the end of the buffer. + ** This is in case the sample record is corrupted. In that case, the + ** sqlite3VdbeRecordCompare() may read up to two varints past the + ** end of the allocated buffer before it realizes it is dealing with + ** a corrupt record. Adding the two 0x00 bytes prevents this from causing + ** a buffer overread. */ pSample->n = sqlite3_column_bytes(pStmt, 4); - pSample->p = sqlite3DbMallocZero(db, pSample->n); + pSample->p = sqlite3DbMallocZero(db, pSample->n + 2); if( pSample->p==0 ){ sqlite3_finalize(pStmt); return SQLITE_NOMEM; } memcpy(pSample->p, sqlite3_column_blob(pStmt, 4), pSample->n); + pIdx->nSample++; } rc = sqlite3_finalize(pStmt); if( rc==SQLITE_OK ) initAvgEq(pPrevIdx); diff --git a/test/analyze9.test b/test/analyze9.test index 7e67c5f832..33d823ba99 100644 --- a/test/analyze9.test +++ b/test/analyze9.test @@ -291,7 +291,7 @@ do_execsql_test 5.1 { } #------------------------------------------------------------------------- -# This was also crashing. +# This was also crashing (corrupt sqlite_stat4 table). # reset_db do_execsql_test 6.1 { @@ -317,5 +317,31 @@ do_execsql_test 6.2 { SELECT * FROM t1 WHERE a = 'abc'; } +#------------------------------------------------------------------------- +# The following tests experiment with adding corrupted records to the +# 'sample' column of the sqlite_stat4 table. +# +reset_db +sqlite3_db_config_lookaside db 0 0 0 + +do_execsql_test 7.1 { + CREATE TABLE t1(a, b); + CREATE INDEX i1 ON t1(a, b); + INSERT INTO t1 VALUES(1, 1); + INSERT INTO t1 VALUES(2, 2); + INSERT INTO t1 VALUES(3, 3); + INSERT INTO t1 VALUES(4, 4); + INSERT INTO t1 VALUES(5, 5); + ANALYZE; + UPDATE sqlite_stat4 SET sample = X'' WHERE rowid = 1; + ANALYZE sqlite_master; +} + +do_execsql_test 7.2 { + UPDATE sqlite_stat4 SET sample = X'FFFF'; + ANALYZE sqlite_master; + SELECT * FROM t1 WHERE a = 1; +} {1 1} + finish_test