Skip to content

Commit df38157

Browse files
committed
In hstore_plpython, avoid crashing when return value isn't a mapping.
Python 3 changed the behavior of PyMapping_Check(), breaking the test in plpython_to_hstore() that verifies whether a function result to be transformed is acceptable. A backwards-compatible fix is to first verify that the object doesn't pass PySequence_Check(). Perhaps accidentally, our other uses of PyMapping_Check() already follow uses of PySequence_Check(), so that no other bugs were created by this change. Per bug #17908 from Alexander Lakhin. Back-patch to all supported branches. Dmitry Dolgov and Tom Lane Discussion: https://postgr.es/m/17908-3f19a125d56a11d6@postgresql.org
1 parent 376dc82 commit df38157

File tree

3 files changed

+29
-1
lines changed

3 files changed

+29
-1
lines changed

contrib/hstore_plpython/expected/hstore_plpython.out

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,17 @@ INFO: [('aa', 'bb'), ('cc', None)]
3232
2
3333
(1 row)
3434

35+
-- test that a non-mapping result is correctly rejected
36+
CREATE FUNCTION test1bad() RETURNS hstore
37+
LANGUAGE plpython3u
38+
TRANSFORM FOR TYPE hstore
39+
AS $$
40+
return "foo"
41+
$$;
42+
SELECT test1bad();
43+
ERROR: not a Python mapping
44+
CONTEXT: while creating return value
45+
PL/Python function "test1bad"
3546
-- test hstore[] -> python
3647
CREATE FUNCTION test1arr(val hstore[]) RETURNS int
3748
LANGUAGE plpython3u

contrib/hstore_plpython/hstore_plpython.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,13 @@ plpython_to_hstore(PG_FUNCTION_ARGS)
127127
HStore *volatile out;
128128

129129
dict = (PyObject *) PG_GETARG_POINTER(0);
130-
if (!PyMapping_Check(dict))
130+
131+
/*
132+
* As of Python 3, PyMapping_Check() is unreliable unless one first checks
133+
* that the object isn't a sequence. (Cleaner solutions exist, but not
134+
* before Python 3.10, which we're not prepared to require yet.)
135+
*/
136+
if (PySequence_Check(dict) || !PyMapping_Check(dict))
131137
ereport(ERROR,
132138
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
133139
errmsg("not a Python mapping")));

contrib/hstore_plpython/sql/hstore_plpython.sql

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,17 @@ $$;
2727
SELECT test1n('aa=>bb, cc=>NULL'::hstore);
2828

2929

30+
-- test that a non-mapping result is correctly rejected
31+
CREATE FUNCTION test1bad() RETURNS hstore
32+
LANGUAGE plpython3u
33+
TRANSFORM FOR TYPE hstore
34+
AS $$
35+
return "foo"
36+
$$;
37+
38+
SELECT test1bad();
39+
40+
3041
-- test hstore[] -> python
3142
CREATE FUNCTION test1arr(val hstore[]) RETURNS int
3243
LANGUAGE plpython3u

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy