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:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user