static SV *plperl_hash_from_tuple(HeapTuple tuple, TupleDesc tupdesc, bool include_generated);
static SV *plperl_hash_from_datum(Datum attr);
+static void check_spi_usage_allowed(void);
static SV *plperl_ref_from_pg_array(Datum arg, Oid typid);
static SV *split_array(plperl_array_info *info, int first, int last, int nest);
static SV *make_array_ref(plperl_array_info *info, int first, int last);
char *
plperl_sv_to_literal(SV *sv, char *fqtypename)
{
- Datum str = CStringGetDatum(fqtypename);
- Oid typid = DirectFunctionCall1(regtypein, str);
+ Oid typid;
Oid typoutput;
Datum datum;
bool typisvarlena,
isnull;
+ check_spi_usage_allowed();
+
+ typid = DirectFunctionCall1(regtypein, CStringGetDatum(fqtypename));
if (!OidIsValid(typid))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
/* simple croak as we don't want to involve PostgreSQL code */
croak("SPI functions can not be used in END blocks");
}
+
+ /*
+ * Disallow SPI usage if we're not executing a fully-compiled plperl
+ * function. It might seem impossible to get here in that case, but there
+ * are cases where Perl will try to execute code during compilation. If
+ * we proceed we are likely to crash trying to dereference the prodesc
+ * pointer. Working around that might be possible, but it seems unwise
+ * because it'd allow code execution to happen while validating a
+ * function, which is undesirable.
+ */
+ if (current_call_data == NULL || current_call_data->prodesc == NULL)
+ {
+ /* simple croak as we don't want to involve PostgreSQL code */
+ croak("SPI functions can not be used during function compilation");
+ }
}
{
MemoryContext oldcontext = CurrentMemoryContext;
+ check_spi_usage_allowed();
+
PG_TRY();
{
plperl_return_next_internal(sv);
{
MemoryContext oldcontext = CurrentMemoryContext;
+ check_spi_usage_allowed();
+
PG_TRY();
{
SPI_commit();
{
MemoryContext oldcontext = CurrentMemoryContext;
+ check_spi_usage_allowed();
+
PG_TRY();
{
SPI_rollback();
MemoryContext oldcontext = CurrentMemoryContext;
char *volatile cmsg = NULL;
+ /*
+ * We intentionally omit check_spi_usage_allowed() here, as this seems
+ * safe to allow even in the contexts that that function rejects.
+ */
+
PG_TRY();
{
cmsg = sv2cstr(msg);