summaryrefslogtreecommitdiff
path: root/src
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
commitd45fb6e9d8ca02c4e047d43cb493066a372256d3 (patch)
tree43da5681d08f5bf63eb038beb253f52f74e013ad /src
parentb052d524ca712450b0853bb0d5dbd2d2ce139c05 (diff)
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
Diffstat (limited to 'src')
-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 0add733984d..27df4c233f6 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;
}
}