Use portal pinning in PL/Perl and PL/Python
authorPeter Eisentraut <peter_e@gmx.net>
Tue, 12 Dec 2017 15:26:47 +0000 (10:26 -0500)
committerPeter Eisentraut <peter_e@gmx.net>
Wed, 10 Jan 2018 22:10:32 +0000 (17:10 -0500)
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.)

src/pl/plperl/plperl.c
src/pl/plpython/plpy_cursorobject.c

index 41fd0ba42148f3836514b943948eb778343aa6a6..10feef11cf3c245caf9577ce605afb9a2e861af6 100644 (file)
@@ -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);
index 9467f648082dbffd92dd35578d694cb0df1778e8..a527585b81829eb5791f3f6e866136b72d7659f8 100644 (file)
@@ -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;
        }