Skip to content

Commit 70d6226

Browse files
committed
Use portal pinning in PL/Perl and PL/Python
PL/pgSQL "pins" internally generated portals so that user code cannot close them by guessing their names. Add this functionality to PL/Perl and PL/Python as well, preventing users from manually closing cursors created by spi_query and plpy.cursor, respectively. (PL/Tcl does not currently offer any cursor functionality.)
1 parent 5115854 commit 70d6226

File tree

2 files changed

+16
-0
lines changed

2 files changed

+16
-0
lines changed

src/pl/plperl/plperl.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3406,6 +3406,8 @@ plperl_spi_query(char *query)
34063406
SPI_result_code_string(SPI_result));
34073407
cursor = cstr2sv(portal->name);
34083408

3409+
PinPortal(portal);
3410+
34093411
/* Commit the inner transaction, return to outer xact context */
34103412
ReleaseCurrentSubTransaction();
34113413
MemoryContextSwitchTo(oldcontext);
@@ -3469,6 +3471,7 @@ plperl_spi_fetchrow(char *cursor)
34693471
SPI_cursor_fetch(p, true, 1);
34703472
if (SPI_processed == 0)
34713473
{
3474+
UnpinPortal(p);
34723475
SPI_cursor_close(p);
34733476
row = &PL_sv_undef;
34743477
}
@@ -3520,7 +3523,10 @@ plperl_spi_cursor_close(char *cursor)
35203523
p = SPI_cursor_find(cursor);
35213524

35223525
if (p)
3526+
{
3527+
UnpinPortal(p);
35233528
SPI_cursor_close(p);
3529+
}
35243530
}
35253531

35263532
SV *
@@ -3884,6 +3890,8 @@ plperl_spi_query_prepared(char *query, int argc, SV **argv)
38843890

38853891
cursor = cstr2sv(portal->name);
38863892

3893+
PinPortal(portal);
3894+
38873895
/* Commit the inner transaction, return to outer xact context */
38883896
ReleaseCurrentSubTransaction();
38893897
MemoryContextSwitchTo(oldcontext);

src/pl/plpython/plpy_cursorobject.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,8 @@ PLy_cursor_query(const char *query)
151151

152152
cursor->portalname = MemoryContextStrdup(cursor->mcxt, portal->name);
153153

154+
PinPortal(portal);
155+
154156
PLy_spi_subtransaction_commit(oldcontext, oldowner);
155157
}
156158
PG_CATCH();
@@ -266,6 +268,8 @@ PLy_cursor_plan(PyObject *ob, PyObject *args)
266268

267269
cursor->portalname = MemoryContextStrdup(cursor->mcxt, portal->name);
268270

271+
PinPortal(portal);
272+
269273
PLy_spi_subtransaction_commit(oldcontext, oldowner);
270274
}
271275
PG_CATCH();
@@ -317,7 +321,10 @@ PLy_cursor_dealloc(PyObject *arg)
317321
portal = GetPortalByName(cursor->portalname);
318322

319323
if (PortalIsValid(portal))
324+
{
325+
UnpinPortal(portal);
320326
SPI_cursor_close(portal);
327+
}
321328
cursor->closed = true;
322329
}
323330
if (cursor->mcxt)
@@ -508,6 +515,7 @@ PLy_cursor_close(PyObject *self, PyObject *unused)
508515
return NULL;
509516
}
510517

518+
UnpinPortal(portal);
511519
SPI_cursor_close(portal);
512520
cursor->closed = true;
513521
}

0 commit comments

Comments
 (0)