postgres.git / summary / log / commit / refs

commit    b57f962201b248c65d6034176871b28bc04072dc
Author:   Fujii Masao <fujii@postgresql.org>
Date:     Wed Aug 19 03:31:00 2026 +0000

    psql: Avoid returning oom_buffer from psql slash command scanner
    
    psql_scan_slash_command() builds the command name in a local
    PQExpBufferData and returns the buffer's data pointer to its caller. If
    either the initial allocation or a later enlargement failed, that data
    pointer could be the static PQExpBuffer OOM buffer rather than malloc-owned
    storage. HandleSlashCmds() could then eventually pass it to free(), causing
    undefined behavior.
    
    Detect a broken command-name buffer before returning it, report OOM, and
    return NULL instead. Teach HandleSlashCmds() to treat a NULL command name
    as a command error before trying to compare or dispatch it.
    
    Backpatch to all supported versions.
    
    Reported-by: Junwang Zhao <zhjwpku@gmail.com>
    Author: Fujii Masao <masao.fujii@gmail.com>
    Reviewed-by: Chao Li <li.evan.chao@gmail.com>
    Reviewed-by: Junwang Zhao <zhjwpku@gmail.com>
    Discussion: https://postgr.es/m/CAHGQGwEh3R3=1tx_a5=fTDJ+ycuwxWMEn6bG_Yt4B5P+hE7AVw@mail.gmail.com
    Backpatch-through: 14


src/bin/psql/command.c | 4 +++- src/bin/psql/psqlscanslash.l | 15 +++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index ae3ab3295d5..be9e3b035e2 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -236,7 +236,9 @@ HandleSlashCmds(PsqlScanState scan_state, * If we are in "restricted" mode, the only allowable backslash command is * \unrestrict (to exit restricted mode). */ - if (restricted && strcmp(cmd, "unrestrict") != 0) + if (cmd == NULL) + status = PSQL_CMD_ERROR; + else if (restricted && strcmp(cmd, "unrestrict") != 0) { pg_log_error("backslash commands are restricted; only \\unrestrict is allowed"); status = PSQL_CMD_ERROR; diff --git a/src/bin/psql/psqlscanslash.l b/src/bin/psql/psqlscanslash.l index a917d1ec180..0af91cba6bd 100644 --- a/src/bin/psql/psqlscanslash.l +++ b/src/bin/psql/psqlscanslash.l @@ -479,7 +479,7 @@ other . * has been consumed through the leading backslash. * * The return value is a malloc'd copy of the command name, as parsed off - * from the input. + * from the input, or NULL on out-of-memory. */ char * psql_scan_slash_command(PsqlScanState state) @@ -510,7 +510,7 @@ psql_scan_slash_command(PsqlScanState state) /* And lex. */ yylex(NULL, state->scanner); - /* There are no possible errors in this lex state... */ + /* There are no possible syntax errors in this lex state... */ /* * In case the caller returns to using the regular SQL lexer, reselect the @@ -518,6 +518,17 @@ psql_scan_slash_command(PsqlScanState state) */ psql_scan_reselect_sql_lexer(state); + /* + * yylex() appends command-name text to mybuf, so a buffer enlargement + * failure during lexing can leave mybuf broken even if initialization + * succeeded. + */ + if (PQExpBufferDataBroken(mybuf)) + { + pg_log_error("out of memory"); + return NULL; + } + return mybuf.data; } [parent: 402e9624444b]