1
0
mirror of https://github.com/postgres/postgres.git synced 2026-10-23 13:29:09 +03:00

psql: Avoid returning oom_buffer from psql slash option scanner

psql_scan_slash_option() builds option text 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.
The callers could then eventually pass it to free(), causing undefined
behavior.

Detect a broken option buffer before returning it, report OOM, and return
NULL instead. Also avoid evaluating a backtick substitution when the option
buffer is already broken, since doing so could otherwise touch the static
OOM buffer.

This keeps the existing NULL-return convention for slash options. Callers
are not generally changed to distinguish OOM from no option.

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
This commit is contained in:
Fujii Masao
2026-08-19 12:34:28 +09:00
parent 3d41f014f1
commit 1c62efd142
2 changed files with 23 additions and 3 deletions

View File

@@ -2007,7 +2007,7 @@ exec_command_lo(PsqlScanState scan_state, bool active_branch, const char *cmd)
if (strcmp(cmd + 3, "export") == 0)
{
if (!opt2)
if (!opt1 || !opt2)
{
pg_log_error("\\%s: missing required argument", cmd);
success = false;

View File

@@ -536,7 +536,8 @@ psql_scan_slash_command(PsqlScanState state)
/*
* Parse off the next argument for a backslash command, and return it as a
* malloc'd string. If there are no more arguments, returns NULL.
* malloc'd string. If there are no more arguments or on out-of-memory,
* returns NULL.
*
* type tells what processing, if any, to perform on the option string;
* for example, if it's a SQL identifier, we want to downcase any unquoted
@@ -613,6 +614,16 @@ psql_scan_slash_option(PsqlScanState state,
*/
Assert(lexresult == LEXRES_EOL || lexresult == LEXRES_OK);
/*
* yylex() appends option 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;
}
switch (final_state)
{
case xslashargstart:
@@ -821,7 +832,7 @@ static void
evaluate_backtick(PsqlScanState state)
{
PQExpBuffer output_buf = state->output_buf;
char *cmd = output_buf->data + backtick_start_offset;
char *cmd;
PQExpBufferData cmd_output;
FILE *fd;
bool error = false;
@@ -829,6 +840,15 @@ evaluate_backtick(PsqlScanState state)
char buf[512];
size_t result;
/*
* The option buffer is already broken; avoid touching the static
* oom_buffer and let psql_scan_slash_option() return NULL.
*/
if (PQExpBufferBroken(output_buf))
return;
cmd = output_buf->data + backtick_start_offset;
initPQExpBuffer(&cmd_output);
fflush(NULL);