Skip to content

Commit 9fca7e8

Browse files
committed
fix crash of plpgsql_check due access to invalid memory when Cursor leaks detection is processed.
Cursor leaks detection uses memory from Top Transaction Context. Unfortunately, this memory can be invalidated inside function execution (when transaction is ended inside procedure). Originaly pointer to transaction context was stored as plugin2 info. After fix, the plugin2 info is pointer to fn_mcxt context structure with pointer to transaction memory and transaction id. Before any access to transaction memory, the transaction id is checked.
1 parent 639bcbf commit 9fca7e8

File tree

3 files changed

+43
-11
lines changed

3 files changed

+43
-11
lines changed

src/cursors_leaks.c

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ typedef struct
4646
CursorTrace *cursors_traces;
4747
} FunctionTrace;
4848

49+
typedef struct
50+
{
51+
FunctionTrace *ftrace;
52+
LocalTransactionId lxid;
53+
} CursorLeaksPlugin2Info;
54+
4955
MemoryContextCallback contextCallback;
5056

5157
static LocalTransactionId traces_lxid = InvalidLocalTransactionId;
@@ -121,13 +127,18 @@ get_function_trace(PLpgSQL_function *func)
121127
static void
122128
func_setup(PLpgSQL_execstate *estate, PLpgSQL_function *func, void **plugin2_info)
123129
{
124-
FunctionTrace *ftrace;
125-
126130
if (plpgsql_check_cursors_leaks)
127131
{
128-
ftrace = get_function_trace(func);
132+
CursorLeaksPlugin2Info *pinfo;
133+
MemoryContext fn_mcxt;
134+
135+
fn_mcxt = plpgsql_check_get_current_fn_mcxt();
136+
pinfo = MemoryContextAlloc(fn_mcxt, sizeof(CursorLeaksPlugin2Info));
129137

130-
*plugin2_info = ftrace;
138+
pinfo->ftrace = get_function_trace(func);
139+
pinfo->lxid = CURRENT_LXID;
140+
141+
*plugin2_info = pinfo;
131142
}
132143
else
133144
*plugin2_info = NULL;
@@ -138,12 +149,15 @@ func_end(PLpgSQL_execstate *estate,
138149
PLpgSQL_function *func,
139150
void **plugin2_info)
140151
{
141-
FunctionTrace *ftrace = *plugin2_info;
152+
CursorLeaksPlugin2Info *pinfo = *plugin2_info;
153+
FunctionTrace *ftrace;
142154
int i;
143155

144-
if (!ftrace || traces_lxid != CURRENT_LXID)
156+
if (!pinfo || pinfo->lxid != CURRENT_LXID)
145157
return;
146158

159+
ftrace = pinfo->ftrace;
160+
147161
for (i = 0; i < ftrace->ncursors; i++)
148162
{
149163
CursorTrace *ct = &ftrace->cursors_traces[i];
@@ -186,17 +200,23 @@ func_end(PLpgSQL_execstate *estate,
186200
static void
187201
stmt_end(PLpgSQL_execstate *estate, PLpgSQL_stmt *stmt, void **plugin2_info)
188202
{
189-
FunctionTrace *ftrace = *plugin2_info;
203+
CursorLeaksPlugin2Info *pinfo = *plugin2_info;
204+
FunctionTrace *ftrace;
190205

191-
if (!ftrace)
206+
if (!pinfo)
192207
return;
193208

194-
if (traces_lxid != CURRENT_LXID)
209+
if (traces_lxid != CURRENT_LXID ||
210+
pinfo->lxid != CURRENT_LXID)
195211
{
196-
ftrace = get_function_trace(estate->func);
197-
*plugin2_info = ftrace;
212+
pinfo->ftrace = get_function_trace(estate->func);
213+
pinfo->lxid = CURRENT_LXID;
214+
215+
*plugin2_info = pinfo;
198216
}
199217

218+
ftrace = pinfo->ftrace;
219+
200220
if (stmt->cmd_type == PLPGSQL_STMT_OPEN)
201221
{
202222
int i;

src/pldbgapi2.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ plpgsql_check_get_current_stmts_info(void)
160160
return current_fmgr_plpgsql_cache->func_info->stmts_info;
161161
}
162162

163+
163164
/*
164165
* It is used outside pldbapi2 plugins. This is used by output functions,
165166
* so we don't need to solve effectivity too much. Instead handling use_count
@@ -226,6 +227,16 @@ plpgsql_check_get_current_func_info_signature(void)
226227
return current_fmgr_plpgsql_cache->func_info->fn_signature;
227228
}
228229

230+
MemoryContext
231+
plpgsql_check_get_current_fn_mcxt(void)
232+
{
233+
Assert(current_fmgr_plpgsql_cache);
234+
Assert(current_fmgr_plpgsql_cache->func_info);
235+
Assert(current_fmgr_plpgsql_cache->func_info->use_count > 0);
236+
237+
return current_fmgr_plpgsql_cache->fn_mcxt;
238+
}
239+
229240
static void
230241
func_info_init_hashkey(func_info_hashkey *hk, PLpgSQL_function *func)
231242
{

src/plpgsql_check.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,7 @@ extern int *plpgsql_check_get_stmtid_map(PLpgSQL_function *func);
455455

456456
extern char *plpgsql_check_get_current_func_info_name(void);
457457
extern char *plpgsql_check_get_current_func_info_signature(void);
458+
extern MemoryContext plpgsql_check_get_current_fn_mcxt(void);
458459

459460
#if PG_VERSION_NUM < 150000
460461

0 commit comments

Comments
 (0)