Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Avoid buffer overreads and false OOM error reports that could be caused by corrupted sample records in the sqlite_stat4 table. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | sqlite_stat4 |
Files: | files | file ages | folders |
SHA1: |
9f85b6a52a0b9b1524daa6f24d85257e |
User & Date: | dan 2013-08-16 14:09:43.262 |
Context
2013-08-16
| ||
14:23 | Add extra tests. No code changes. (check-in: 949127d53e user: dan tags: sqlite_stat4) | |
14:09 | Avoid buffer overreads and false OOM error reports that could be caused by corrupted sample records in the sqlite_stat4 table. (check-in: 9f85b6a52a user: dan tags: sqlite_stat4) | |
13:34 | Fix a potential segfault following an OOM while running ANALYZE. (check-in: 0118797823 user: drh tags: sqlite_stat4) | |
Changes
Changes to src/analyze.c.
︙ | ︙ | |||
1407 1408 1409 1410 1411 1412 1413 | ** the sqlite_stat4 table. In this case ignore stat3 data. */ nCol = pIdx->nSampleCol; if( bStat3 && nCol>1 ) continue; if( pIdx!=pPrevIdx ){ initAvgEq(pPrevIdx); pPrevIdx = pIdx; } | | > > > > > > | > | 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 | ** the sqlite_stat4 table. In this case ignore stat3 data. */ nCol = pIdx->nSampleCol; if( bStat3 && nCol>1 ) continue; if( pIdx!=pPrevIdx ){ initAvgEq(pPrevIdx); pPrevIdx = pIdx; } 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 + 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); return rc; } /* |
︙ | ︙ |
Changes to test/analyze9.test.
︙ | ︙ | |||
287 288 289 290 291 292 293 | do_execsql_test 5.1 { PRAGMA encoding = 'utf-16'; CREATE TABLE t0(v); ANALYZE; } #------------------------------------------------------------------------- | | | 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 | do_execsql_test 5.1 { PRAGMA encoding = 'utf-16'; CREATE TABLE t0(v); ANALYZE; } #------------------------------------------------------------------------- # This was also crashing (corrupt sqlite_stat4 table). # reset_db do_execsql_test 6.1 { CREATE TABLE t1(a, b); CREATE INDEX i1 ON t1(a); CREATE INDEX i2 ON t1(b); INSERT INTO t1 VALUES(1, 1); |
︙ | ︙ | |||
312 313 314 315 316 317 318 319 320 321 | INSERT INTO sqlite_stat4 SELECT * FROM x1; PRAGMA writable_schema = 0; ANALYZE sqlite_master; } do_execsql_test 6.2 { SELECT * FROM t1 WHERE a = 'abc'; } finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > | 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 | INSERT INTO sqlite_stat4 SELECT * FROM x1; PRAGMA writable_schema = 0; ANALYZE sqlite_master; } 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 |