From ba10f2054893a29df5d4f1c0ef4950e4c1841482 Mon Sep 17 00:00:00 2001 From: Fujii Masao Date: Thu, 13 Aug 2026 00:14:58 +0900 Subject: [PATCH v2 1/3] 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() would 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. --- 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 190c5c6f77a..f80839266e6 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -249,7 +249,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 e3ec1775e62..9640d6e6a6e 100644 --- a/src/bin/psql/psqlscanslash.l +++ b/src/bin/psql/psqlscanslash.l @@ -474,7 +474,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) @@ -505,7 +505,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 @@ -513,6 +513,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; } -- 2.55.0