postgres.git / summary / log / commit / refs

commit    6d2ef1cb99ebaa334c9f0406be142635d02c53d0
Author:   Tom Lane <tgl@sss.pgh.pa.us>
Date:     Fri Oct 06 16:20:13 2017 +0000

    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


src/backend/access/transam/clog.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 4ef9512c17d..7ac7d37b4d7 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; } } [parent: c9c37e335e3a]