Fix access-off-end-of-array in clog.c.
authorTom Lane
Fri, 6 Oct 2017 16:20:13 +0000 (12:20 -0400)
committerTom Lane
Fri, 6 Oct 2017 16:20:13 +0000 (12:20 -0400)
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

src/backend/access/transam/clog.c

index ace2413bdf64e33a2fb50f53129a65408ea77dc6..b9ab2a9c3322a9a8e99040a921d025c532d5c1cd 100644 (file)
@@ -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;
    }
 }