BUG #15540: Use after release in ExecuteTruncateGuts - Mailing list pgsql-bugs

From PG Bug reporting form
Subject BUG #15540: Use after release in ExecuteTruncateGuts
Date
Msg-id 15540-01078812338195c0@postgresql.org
Whole thread Raw
Responses Re: BUG #15540: Use after release in ExecuteTruncateGuts
List pgsql-bugs
The following bug has been logged on the website:

Bug reference:      15540
Logged by:          Pan Bian
Email address:      bianpan2016@163.com
PostgreSQL version: 11.1
Operating system:   Linux
Description:

File: src/backend/commands/tablecmds.c
Function: ExecuteTruncateGuts
Issue details:
The function ExecuteTruncateGuts drops the reference to rel via
relation_close when toast_relid is valid. However, after that, rel is passed
to pgstat_count_truncate. This may result in a use-after-release bug. Maybe,
rel should be re-declared on the branch that toast_relid is valid.

For your convenience, I copy-and-paste related code as follows:

void
ExecuteTruncateGuts(List *explicit_rels, List *relids, List
*relids_logged,
                    DropBehavior behavior, bool restart_seqs)
{
    ...
    foreach(cell, rels)
    {
        Relation    rel = (Relation) lfirst(cell);
        ...
        if (rel->rd_createSubid == mySubid ||
            rel->rd_newRelfilenodeSubid == mySubid)
        {
            /* Immediate, non-rollbackable truncation is OK */
            heap_truncate_one_rel(rel);
        }
        else
        {
            Oid         heap_relid;
            Oid         toast_relid;
            ...
            toast_relid = rel->rd_rel->reltoastrelid;

            /*
             * The same for the toast table, if any.
             */
            if (OidIsValid(toast_relid))
            {
                rel = relation_open(toast_relid, AccessExclusiveLock);
//### open a relation
                RelationSetNewRelfilenode(rel,
rel->rd_rel->relpersistence,
                                          RecentXmin, minmulti);
                if (rel->rd_rel->relpersistence ==
RELPERSISTENCE_UNLOGGED)
                    heap_create_init_fork(rel);
                heap_close(rel, NoLock);   //### release the relation
            }

            /*
             * Reconstruct the indexes to match, and we're done.
             */
            reindex_relation(heap_relid, REINDEX_REL_PROCESS_TOAST, 0);
        }

        pgstat_count_truncate(rel);   //### the released relation is used
again
    }
}

Thank you,
Pan Bian


pgsql-bugs by date:

Previous
From: PG Bug reporting form
Date:
Subject: BUG #15539: Deadcode in OpenTableList
Next
From: PG Bug reporting form
Date:
Subject: BUG #15541: Use after release in PQprint