Hi hackers, The allocations in src/backend/commands/explain_state.c used sizeof(char *) instead of sizeof(ExplainExtensionOption), which could cause a crash if an extension would register more than 8 extension EXPLAIN options:
Attached small example extension, test_explain_state.txt,
to demonstrate the bug:
LOAD 'test_explain_state';
LOAD
EXPLAIN (test_explain_opt9) SELECT 1;
server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
connection to server was lost
/Joel
/*-------------------------------------------------------------------------
*
* test_explain_state.c
* Crash reproducer for the sizeof bug in RegisterExtensionExplainOption.
*
* RegisterExtensionExplainOption allocates its
ExplainExtensionOptionArray
* using sizeof(char *) (8 bytes) instead of
sizeof(ExplainExtensionOption)
* (16 bytes). The initial allocation is for 16 "slots" at 8 bytes each
=
* 128 bytes, but each ExplainExtensionOption is 16 bytes, so only 8
entries
* actually fit. Registering a 9th option writes past the end of the
* allocation, corrupting the heap.
*
* This module registers 10 options, which is enough to trigger the bug.
*/
#include "postgres.h"
#include "commands/defrem.h"
#include "commands/explain_state.h"
#include "fmgr.h"
PG_MODULE_MAGIC;
static const char *const option_names[] = {
"test_explain_opt0",
"test_explain_opt1",
"test_explain_opt2",
"test_explain_opt3",
"test_explain_opt4",
"test_explain_opt5",
"test_explain_opt6",
"test_explain_opt7",
"test_explain_opt8",
"test_explain_opt9",
};
#define NUM_OPTIONS lengthof(option_names)
static void test_explain_option_handler(ExplainState *es, DefElem *opt,
ParseState *pstate);
void
_PG_init(void)
{
for (int i = 0; i < NUM_OPTIONS; i++)
RegisterExtensionExplainOption(option_names[i],
test_explain_option_handler);
}
static void
test_explain_option_handler(ExplainState *es, DefElem *opt,
ParseState *pstate)
{
ereport(NOTICE,
(errmsg("test_explain_state: processed option \"%s\"",
opt->defname)));
}
0001-Fix-sizeof-bug-in-RegisterExtensionExplainOption.patch
Description: Binary data
