diff options
| author | Fujii Masao | 2026-08-19 03:31:00 +0000 |
|---|---|---|
| committer | Fujii Masao | 2026-08-19 03:33:59 +0000 |
| commit | b57f962201b248c65d6034176871b28bc04072dc (patch) | |
| tree | aa819baa16b70d01ba90d7fe7b3a5692341243de | |
| parent | 402e9624444b3b3c3f75c90d3b3d847dcfa1b8f9 (diff) | |
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
| -rw-r--r-- | src/bin/psql/command.c | 4 | ||||
| -rw-r--r-- | 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; } |
