aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2017-10-06 12:20:13 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2017-10-06 12:20:13 -0400
commitc209b5034ecb7cfa2bd09c960bdf0a22afaa0986 (patch)
tree7407abd6be6e7010893bac71be97bf4bd642c526
parent8b6d85f2dc1ed01fc3272703abb2c267859468eb (diff)
downloadpostgresql-c209b5034ecb7cfa2bd09c960bdf0a22afaa0986.tar.gz
postgresql-c209b5034ecb7cfa2bd09c960bdf0a22afaa0986.zip
Fix access-off-end-of-array in clog.c.
Sloppy loop coding in set_status_by_pages() resulted in fetching one array element more than it should from the subxids[] array. The odds of this resulting in SIGSEGV are pretty small, but we've certainly seen that happen with similar mistakes elsewhere. While at it, we can get rid of an extra TransactionIdToPage() calculation per loop. Per report from David Binderman. Back-patch to all supported branches, since this code is quite old. Discussion: https://postgr.es/m/HE1PR0802MB2331CBA919CBFFF0C465EB429C710@HE1PR0802MB2331.eurprd08.prod.outlook.com
-rw-r--r--src/backend/access/transam/clog.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c
index ace2413bdf6..b9ab2a9c332 100644
--- a/src/backend/access/transam/clog.c
+++ b/src/backend/access/transam/clog.c
@@ -223,21 +223,27 @@ set_status_by_pages(int nsubxids, TransactionId *subxids,
int offset = 0;
int i = 0;
+ Assert(nsubxids > 0); /* else the pageno fetch above is unsafe */
+
while (i < nsubxids)
{
int num_on_page = 0;
+ int nextpageno;
- while (TransactionIdToPage(subxids[i]) == pageno && i < nsubxids)
+ do
{
+ nextpageno = TransactionIdToPage(subxids[i]);
+ if (nextpageno != pageno)
+ break;
num_on_page++;
i++;
- }
+ } while (i < nsubxids);
TransactionIdSetPageStatus(InvalidTransactionId,
num_on_page, subxids + offset,
status, lsn, pageno);
offset = i;
- pageno = TransactionIdToPage(subxids[offset]);
+ pageno = nextpageno;
}
}