PG-613: Postgresql crashes with Segmentation fault when query plan is enabled on large queries

The return value for snprintf was incorrectly being recorded as plan
length. That's been resolved.

As part of this fix, we've also elminated the possibility of a potential
memory leak when plan text was being saved.

Co-authored-by: Hamid Akhtar <hamid.akhtar@percona.com>
Co-authored-by: Muhammad Usama <muhammad.usama@percona.com>
pull/399/head
Hamid Akhtar 2023-04-18 18:01:34 +05:00 committed by Muhammad Usama
parent 7623f15e68
commit 2ceb47e3cd
1 changed files with 24 additions and 3 deletions

View File

@ -692,11 +692,32 @@ pgsm_ExecutorEnd(QueryDesc *queryDesc)
/* Extract the plan information in case of SELECT statement */ /* Extract the plan information in case of SELECT statement */
if (queryDesc->operation == CMD_SELECT && pgsm_enable_query_plan) if (queryDesc->operation == CMD_SELECT && pgsm_enable_query_plan)
{ {
plan_info.plan_len = snprintf(plan_info.plan_text, PLAN_TEXT_LEN, "%s", pgsm_explain(queryDesc)); int rv;
MemoryContext oldctx;
/*
* Making sure it is a per query context so that there's no memory
* leak when executor ends.
*/
oldctx = MemoryContextSwitchTo(queryDesc->estate->es_query_cxt);
rv = snprintf(plan_info.plan_text, PLAN_TEXT_LEN, "%s", pgsm_explain(queryDesc));
/*
* If snprint didn't write anything or there was an error, let's keep
* planinfo as NULL.
*/
if (rv > 0)
{
plan_info.plan_len = (rv < PLAN_TEXT_LEN) ? rv : PLAN_TEXT_LEN - 1;
plan_info.planid = pgsm_hash_string(plan_info.plan_text, plan_info.plan_len); plan_info.planid = pgsm_hash_string(plan_info.plan_text, plan_info.plan_len);
plan_ptr = &plan_info; plan_ptr = &plan_info;
} }
/* Switch back to old context */
MemoryContextSwitchTo(oldctx);
}
if (queryId != UINT64CONST(0) && queryDesc->totaltime && pgsm_enabled(exec_nested_level)) if (queryId != UINT64CONST(0) && queryDesc->totaltime && pgsm_enabled(exec_nested_level))
{ {
entry = pgsm_get_entry_for_query(queryId, plan_ptr, (char *) queryDesc->sourceText, strlen(queryDesc->sourceText), true); entry = pgsm_get_entry_for_query(queryId, plan_ptr, (char *) queryDesc->sourceText, strlen(queryDesc->sourceText), true);