]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Fix access-off-end-of-array in clog.c.
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 6 Oct 2017 16:20:13 +0000 (12:20 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
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 4ef9512c17dd9d1c1eaa36881072b1a306b67b92..7ac7d37b4d72e189120fd7c9d50f64e7298d821c 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;
        }
 }