diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2017-10-06 12:20:13 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2017-10-06 12:20:13 -0400 |
commit | 4c20ee5f27a2edbf89273e44eb369fd92d4fe3b2 (patch) | |
tree | 9937b858a12ca2b5328e09ef19d39717a8dbc30d | |
parent | 22576734b805fb0952f9be841ca8f643694ee868 (diff) | |
download | postgresql-4c20ee5f27a2edbf89273e44eb369fd92d4fe3b2.tar.gz postgresql-4c20ee5f27a2edbf89273e44eb369fd92d4fe3b2.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.c | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 0a7e2b310f1..41778584ba8 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -227,21 +227,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; } } |