mirror of
https://github.com/postgres/postgres.git
synced 2025-07-07 00:36:50 +03:00
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.)
This commit is contained in:
@ -3406,6 +3406,8 @@ plperl_spi_query(char *query)
|
|||||||
SPI_result_code_string(SPI_result));
|
SPI_result_code_string(SPI_result));
|
||||||
cursor = cstr2sv(portal->name);
|
cursor = cstr2sv(portal->name);
|
||||||
|
|
||||||
|
PinPortal(portal);
|
||||||
|
|
||||||
/* Commit the inner transaction, return to outer xact context */
|
/* Commit the inner transaction, return to outer xact context */
|
||||||
ReleaseCurrentSubTransaction();
|
ReleaseCurrentSubTransaction();
|
||||||
MemoryContextSwitchTo(oldcontext);
|
MemoryContextSwitchTo(oldcontext);
|
||||||
@ -3469,6 +3471,7 @@ plperl_spi_fetchrow(char *cursor)
|
|||||||
SPI_cursor_fetch(p, true, 1);
|
SPI_cursor_fetch(p, true, 1);
|
||||||
if (SPI_processed == 0)
|
if (SPI_processed == 0)
|
||||||
{
|
{
|
||||||
|
UnpinPortal(p);
|
||||||
SPI_cursor_close(p);
|
SPI_cursor_close(p);
|
||||||
row = &PL_sv_undef;
|
row = &PL_sv_undef;
|
||||||
}
|
}
|
||||||
@ -3520,7 +3523,10 @@ plperl_spi_cursor_close(char *cursor)
|
|||||||
p = SPI_cursor_find(cursor);
|
p = SPI_cursor_find(cursor);
|
||||||
|
|
||||||
if (p)
|
if (p)
|
||||||
|
{
|
||||||
|
UnpinPortal(p);
|
||||||
SPI_cursor_close(p);
|
SPI_cursor_close(p);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SV *
|
SV *
|
||||||
@ -3884,6 +3890,8 @@ plperl_spi_query_prepared(char *query, int argc, SV **argv)
|
|||||||
|
|
||||||
cursor = cstr2sv(portal->name);
|
cursor = cstr2sv(portal->name);
|
||||||
|
|
||||||
|
PinPortal(portal);
|
||||||
|
|
||||||
/* Commit the inner transaction, return to outer xact context */
|
/* Commit the inner transaction, return to outer xact context */
|
||||||
ReleaseCurrentSubTransaction();
|
ReleaseCurrentSubTransaction();
|
||||||
MemoryContextSwitchTo(oldcontext);
|
MemoryContextSwitchTo(oldcontext);
|
||||||
|
@ -151,6 +151,8 @@ PLy_cursor_query(const char *query)
|
|||||||
|
|
||||||
cursor->portalname = MemoryContextStrdup(cursor->mcxt, portal->name);
|
cursor->portalname = MemoryContextStrdup(cursor->mcxt, portal->name);
|
||||||
|
|
||||||
|
PinPortal(portal);
|
||||||
|
|
||||||
PLy_spi_subtransaction_commit(oldcontext, oldowner);
|
PLy_spi_subtransaction_commit(oldcontext, oldowner);
|
||||||
}
|
}
|
||||||
PG_CATCH();
|
PG_CATCH();
|
||||||
@ -266,6 +268,8 @@ PLy_cursor_plan(PyObject *ob, PyObject *args)
|
|||||||
|
|
||||||
cursor->portalname = MemoryContextStrdup(cursor->mcxt, portal->name);
|
cursor->portalname = MemoryContextStrdup(cursor->mcxt, portal->name);
|
||||||
|
|
||||||
|
PinPortal(portal);
|
||||||
|
|
||||||
PLy_spi_subtransaction_commit(oldcontext, oldowner);
|
PLy_spi_subtransaction_commit(oldcontext, oldowner);
|
||||||
}
|
}
|
||||||
PG_CATCH();
|
PG_CATCH();
|
||||||
@ -317,7 +321,10 @@ PLy_cursor_dealloc(PyObject *arg)
|
|||||||
portal = GetPortalByName(cursor->portalname);
|
portal = GetPortalByName(cursor->portalname);
|
||||||
|
|
||||||
if (PortalIsValid(portal))
|
if (PortalIsValid(portal))
|
||||||
|
{
|
||||||
|
UnpinPortal(portal);
|
||||||
SPI_cursor_close(portal);
|
SPI_cursor_close(portal);
|
||||||
|
}
|
||||||
cursor->closed = true;
|
cursor->closed = true;
|
||||||
}
|
}
|
||||||
if (cursor->mcxt)
|
if (cursor->mcxt)
|
||||||
@ -508,6 +515,7 @@ PLy_cursor_close(PyObject *self, PyObject *unused)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UnpinPortal(portal);
|
||||||
SPI_cursor_close(portal);
|
SPI_cursor_close(portal);
|
||||||
cursor->closed = true;
|
cursor->closed = true;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user