From 1d190d095ff8e7d11877fc7d4dc82727871a91c1 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 21 Aug 2015 12:21:37 -0400 Subject: Fix plpython crash when returning string representation of a RECORD result. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PLyString_ToComposite() blithely overwrote proc->result.out.d, even though for a composite result type the other union variant proc->result.out.r is the one that should be valid. This could result in a crash if out.r had in fact been filled in (proc->result.is_rowtype == 1) and then somebody later attempted to use that data; as per bug #13579 from Paweł Michalak. Just to add insult to injury, it didn't work for RECORD results anyway, because record_in() would refuse the case. Fix by doing the I/O function lookup in a local PLyTypeInfo variable, as we were doing already in PLyObject_ToComposite(). This is not a great technique because any fn_extra data allocated by the input function will be leaked permanently (thanks to using TopMemoryContext as fn_mcxt). But that's a pre-existing issue that is much less serious than a crash, so leave it to be fixed separately. This bug would be a potential security issue, except that plpython is only available to superusers and the crash requires coding the function in a way that didn't work before today's patches. Add regression test cases covering all the supported methods of converting composite results. Back-patch to 9.1 where the faulty coding was introduced. --- src/pl/plpython/plpython.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'src/pl/plpython/plpython.c') diff --git a/src/pl/plpython/plpython.c b/src/pl/plpython/plpython.c index 4541ffb54d9..3db6f7d23a7 100644 --- a/src/pl/plpython/plpython.c +++ b/src/pl/plpython/plpython.c @@ -2664,18 +2664,28 @@ PLySequence_ToArray(PLyObToDatum *arg, int32 typmod, PyObject *plrv) static Datum PLyString_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *string) { + Datum result; HeapTuple typeTup; + PLyTypeInfo locinfo; + + /* Create a dummy PLyTypeInfo */ + MemSet(&locinfo, 0, sizeof(PLyTypeInfo)); + PLy_typeinfo_init(&locinfo); typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(desc->tdtypeid)); if (!HeapTupleIsValid(typeTup)) elog(ERROR, "cache lookup failed for type %u", desc->tdtypeid); - PLy_output_datum_func2(&info->out.d, typeTup); + PLy_output_datum_func2(&locinfo.out.d, typeTup); ReleaseSysCache(typeTup); ReleaseTupleDesc(desc); - return PLyObject_ToDatum(&info->out.d, info->out.d.typmod, string); + result = PLyObject_ToDatum(&locinfo.out.d, desc->tdtypmod, string); + + PLy_typeinfo_dealloc(&locinfo); + + return result; } -- cgit v1.2.3