postgres.git / summary / log / commit / refs

commit    bea57a6b430c988d628582dd88e27281ccbae796
Author:   David Rowley <drowley@postgresql.org>
Date:     Tue Jan 06 04:29:44 2026 +0000
First released in: 14.21, 15.16, 16.12, 17.8, 18.2

    Fix issue with EVENT TRIGGERS and ALTER PUBLICATION
    
    When processing the "publish" options of an ALTER PUBLICATION command,
    we call SplitIdentifierString() to split the options into a List of
    strings.  Since SplitIdentifierString() modifies the delimiter
    character and puts NULs in their place, this would overwrite the memory
    of the AlterPublicationStmt.  Later in AlterPublicationOptions(), the
    modified AlterPublicationStmt is copied for event triggers, which would
    result in the event trigger only seeing the first "publish" option
    rather than all options that were specified in the command.
    
    To fix this, make a copy of the string before passing to
    SplitIdentifierString().
    
    Here we also adjust a similar case in the pgoutput plugin.  There's no
    known issues caused by SplitIdentifierString() here, so this is being
    done out of paranoia.
    
    Thanks to Henson Choi for putting together an example case showing the
    ALTER PUBLICATION issue.
    
    Author: sunil s <sunilfeb26@gmail.com>
    Reviewed-by: Henson Choi <assam258@gmail.com>
    Reviewed-by: zengman <zengman@halodbtech.com>
    Backpatch-through: 14


src/backend/commands/publicationcmds.c | 7 ++++++- src/backend/replication/pgoutput/pgoutput.c | 6 +++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c index 803c26ab216..0feec8b765a 100644 --- a/src/backend/commands/publicationcmds.c +++ b/src/backend/commands/publicationcmds.c @@ -122,7 +122,12 @@ parse_publication_options(ParseState *pstate, pubactions->pubtruncate = false; *publish_given = true; - publish = defGetString(defel); + + /* + * SplitIdentifierString destructively modifies its input, so make + * a copy so we don't modify the memory of the executing statement + */ + publish = pstrdup(defGetString(defel)); if (!SplitIdentifierString(publish, ',', &publish_list)) ereport(ERROR, diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c index 693ac28de3c..b9ed2291c83 100644 --- a/src/backend/replication/pgoutput/pgoutput.c +++ b/src/backend/replication/pgoutput/pgoutput.c @@ -344,7 +344,11 @@ parse_output_parameters(List *options, PGOutputData *data) errmsg("conflicting or redundant options"))); publication_names_given = true; - if (!SplitIdentifierString(strVal(defel->arg), ',', + /* + * Pass a copy of the DefElem->arg since SplitIdentifierString + * modifies its input. + */ + if (!SplitIdentifierString(pstrdup(strVal(defel->arg)), ',', &data->publication_names)) ereport(ERROR, (errcode(ERRCODE_INVALID_NAME), [parent: 6ec596815125]