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
commit69e931f96ef47e14c62e32b91726ed0d6e7f3d73 (patch)
treef27d3f566debb3084c8e4486d08b886f471d62c3
parentd441cff142490cda2abff60532dd03b345a97fec (diff)
downloadpostgresql-69e931f96ef47e14c62e32b91726ed0d6e7f3d73.tar.gz
postgresql-69e931f96ef47e14c62e32b91726ed0d6e7f3d73.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 263447679b8..73a7f075888 100644
--- a/src/backend/access/transam/clog.c
+++ b/src/backend/access/transam/clog.c
@@ -226,21 +226,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;
}
}