summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Eisentraut2017-12-12 15:26:47 +0000
committerPeter Eisentraut2018-01-10 22:10:32 +0000
commit70d6226e4fba26765877fc3c2ec6c468d3ff4084 (patch)
tree142927e32e7a171802df9ecc4dc13d6e9bb3d03a
parent511585417079b7d52211e09b20de0e0981b6eaa6 (diff)
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.)
-rw-r--r--src/pl/plperl/plperl.c8
-rw-r--r--src/pl/plpython/plpy_cursorobject.c8
2 files changed, 16 insertions, 0 deletions
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c
index 41fd0ba421..10feef11cf 100644
--- a/src/pl/plperl/plperl.c
+++ b/src/pl/plperl/plperl.c
@@ -3406,6 +3406,8 @@ plperl_spi_query(char *query)
SPI_result_code_string(SPI_result));
cursor = cstr2sv(portal->name);
+ PinPortal(portal);
+
/* Commit the inner transaction, return to outer xact context */
ReleaseCurrentSubTransaction();
MemoryContextSwitchTo(oldcontext);
@@ -3469,6 +3471,7 @@ plperl_spi_fetchrow(char *cursor)
SPI_cursor_fetch(p, true, 1);
if (SPI_processed == 0)
{
+ UnpinPortal(p);
SPI_cursor_close(p);
row = &PL_sv_undef;
}
@@ -3520,7 +3523,10 @@ plperl_spi_cursor_close(char *cursor)
p = SPI_cursor_find(cursor);
if (p)
+ {
+ UnpinPortal(p);
SPI_cursor_close(p);
+ }
}
SV *
@@ -3884,6 +3890,8 @@ plperl_spi_query_prepared(char *query, int argc, SV **argv)
cursor = cstr2sv(portal->name);
+ PinPortal(portal);
+
/* Commit the inner transaction, return to outer xact context */
ReleaseCurrentSubTransaction();
MemoryContextSwitchTo(oldcontext);
diff --git a/src/pl/plpython/plpy_cursorobject.c b/src/pl/plpython/plpy_cursorobject.c
index 9467f64808..a527585b81 100644
--- a/src/pl/plpython/plpy_cursorobject.c
+++ b/src/pl/plpython/plpy_cursorobject.c
@@ -151,6 +151,8 @@ PLy_cursor_query(const char *query)
cursor->portalname = MemoryContextStrdup(cursor->mcxt, portal->name);
+ PinPortal(portal);
+
PLy_spi_subtransaction_commit(oldcontext, oldowner);
}
PG_CATCH();
@@ -266,6 +268,8 @@ PLy_cursor_plan(PyObject *ob, PyObject *args)
cursor->portalname = MemoryContextStrdup(cursor->mcxt, portal->name);
+ PinPortal(portal);
+
PLy_spi_subtransaction_commit(oldcontext, oldowner);
}
PG_CATCH();
@@ -317,7 +321,10 @@ PLy_cursor_dealloc(PyObject *arg)
portal = GetPortalByName(cursor->portalname);
if (PortalIsValid(portal))
+ {
+ UnpinPortal(portal);
SPI_cursor_close(portal);
+ }
cursor->closed = true;
}
if (cursor->mcxt)
@@ -508,6 +515,7 @@ PLy_cursor_close(PyObject *self, PyObject *unused)
return NULL;
}
+ UnpinPortal(portal);
SPI_cursor_close(portal);
cursor->closed = true;
}