]> granicus.if.org Git - postgresql/commitdiff
Fix memory corruption/crash in ANALYZE.
authorAndres Freund <andres@anarazel.de>
Tue, 18 Jun 2019 22:51:04 +0000 (15:51 -0700)
committerAndres Freund <andres@anarazel.de>
Tue, 18 Jun 2019 22:51:04 +0000 (15:51 -0700)
This fixes an embarrassing oversight I (Andres) made in 737a292b,
namely missing two place where liverows/deadrows were used when
converting those variables to pointers, leading to incrementing the
pointer, rather than the value.

It's not that actually that easy to trigger a crash: One needs tuples
deleted by the current transaction, followed by a tuple deleted in
another session, all in one page. Which is presumably why this hasn't
been noticed before.

Reported-By: Steve Singer
Author: Steve Singer
Discussion: https://postgr.es/m/c7988239-d42c-ddc4-41db-171b23b35e4f@ssinger.info

src/backend/access/heap/heapam_handler.c
src/test/regress/expected/vacuum.out
src/test/regress/sql/vacuum.sql

index b7d2ddbbdcff3399eea669948ab7cda64ed20583..fc19f40a2e395a4f81fc3e27f26d5ad164f448b3 100644 (file)
@@ -1113,11 +1113,11 @@ heapam_scan_analyze_next_tuple(TableScanDesc scan, TransactionId OldestXmin,
                                 * concurrent transaction never commits.
                                 */
                                if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetUpdateXid(targtuple->t_data)))
-                                       deadrows += 1;
+                                       *deadrows += 1;
                                else
                                {
                                        sample_it = true;
-                                       liverows += 1;
+                                       *liverows += 1;
                                }
                                break;
 
index 21a167fc16ff64ae77e7a9971888d276a27ed448..f944b93fd6f7cd302d79ee6b0a96f0d5c21e2f62 100644 (file)
@@ -71,6 +71,18 @@ ANALYZE vaccluster;
 ERROR:  ANALYZE cannot be executed from VACUUM or ANALYZE
 CONTEXT:  SQL function "do_analyze" statement 1
 SQL function "wrap_do_analyze" statement 1
+-- Test ANALYZE in transaction, where the transaction surrounding
+-- analyze performed modifications. This tests for the bug at
+-- https://postgr.es/m/c7988239-d42c-ddc4-41db-171b23b35e4f%40ssinger.info
+-- (which hopefully is unlikely to be reintroduced), but also seems
+-- independently worthwhile to cover.
+INSERT INTO vactst SELECT generate_series(1, 300);
+DELETE FROM vactst WHERE i % 7 = 0; -- delete a few rows outside
+BEGIN;
+INSERT INTO vactst SELECT generate_series(301, 400);
+DELETE FROM vactst WHERE i % 5 <> 0; -- delete a few rows inside
+ANALYZE vactst;
+COMMIT;
 VACUUM FULL pg_am;
 VACUUM FULL pg_class;
 VACUUM FULL pg_database;
index a558580feafab78ff763608b7ad8f23639c48523..16748e1823f8787a7617fe64e5afec0dfadef29a 100644 (file)
@@ -54,6 +54,19 @@ CREATE INDEX ON vaccluster(wrap_do_analyze(i));
 INSERT INTO vaccluster VALUES (1), (2);
 ANALYZE vaccluster;
 
+-- Test ANALYZE in transaction, where the transaction surrounding
+-- analyze performed modifications. This tests for the bug at
+-- https://postgr.es/m/c7988239-d42c-ddc4-41db-171b23b35e4f%40ssinger.info
+-- (which hopefully is unlikely to be reintroduced), but also seems
+-- independently worthwhile to cover.
+INSERT INTO vactst SELECT generate_series(1, 300);
+DELETE FROM vactst WHERE i % 7 = 0; -- delete a few rows outside
+BEGIN;
+INSERT INTO vactst SELECT generate_series(301, 400);
+DELETE FROM vactst WHERE i % 5 <> 0; -- delete a few rows inside
+ANALYZE vactst;
+COMMIT;
+
 VACUUM FULL pg_am;
 VACUUM FULL pg_class;
 VACUUM FULL pg_database;