Thread
Commits
-
In hstore_plpython, avoid crashing when return value isn't a mapping.
- df38157d9466 16.0 landed
- de2dfa0538f4 13.11 landed
- ce9662598dda 12.15 landed
- c74f88c406dc 14.8 landed
- c3c1097dc543 11.20 landed
- 85ec8bcce260 15.3 landed
-
BUG #17908: plpython_to_hstore() crashes with a non-dict argument
The Post Office <noreply@postgresql.org> — 2023-04-25T13:00:02Z
The following bug has been logged on the website: Bug reference: 17908 Logged by: Alexander Lakhin Email address: exclusion@gmail.com PostgreSQL version: 15.2 Operating system: Ubuntu 22.04 Description: When executing the following query: CREATE EXTENSION hstore_plpython3u CASCADE; CREATE FUNCTION test_transform() RETURNS hstore LANGUAGE plpython3u TRANSFORM FOR TYPE hstore AS 'return "a"'; SELECT test_transform(); The server crashes with the stack trace: Core was generated by `postgres: law regression [local] SELECT '. Program terminated with signal SIGABRT, Aborted. warning: Section `.reg-xstate/3829693' in core file too small. #0 __pthread_kill_implementation (no_tid=0, signo=6, threadid=140451453683648) at ./nptl/pthread_kill.c:44 44 ./nptl/pthread_kill.c: No such file or directory. (gdb) bt #0 __pthread_kill_implementation (no_tid=0, signo=6, threadid=140451453683648) at ./nptl/pthread_kill.c:44 #1 __pthread_kill_internal (signo=6, threadid=140451453683648) at ./nptl/pthread_kill.c:78 #2 __GI___pthread_kill (threadid=140451453683648, signo=signo@entry=6) at ./nptl/pthread_kill.c:89 #3 0x00007fbd66427476 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26 #4 0x00007fbd6640d7f3 in __GI_abort () at ./stdlib/abort.c:79 #5 0x000055eb85f693d7 in __sanitizer::Abort() () #6 0x000055eb85f67271 in __sanitizer::Die() () #7 0x000055eb85f49707 in __asan::ScopedInErrorReport::~ScopedInErrorReport() () #8 0x000055eb85f490b6 in __asan::ReportDeadlySignal(__sanitizer::SignalContext const&) () #9 0x000055eb85f48702 in __asan::AsanOnDeadlySignal(int, void*, void*) () #10 <signal handler called> #11 0x00007fbd1b2c15c8 in PyList_GetItem () from /usr/lib/x86_64-linux-gnu/libpython3.10.so.1.0 #12 0x00007fbd6410ed7f in plpython_to_hstore (fcinfo=0x7ffdc25d0460) at hstore_plpython.c:154 #13 0x000055eb88fcf3a6 in FunctionCall1Coll (flinfo=0x625000177268, collation=0, arg1=140450178140016) at fmgr.c:1124 #14 0x00007fbd1b8194b4 in PLyObject_ToTransform (arg=0x625000177248, plrv=0x7fbd1afa0770, isnull=0x625000184174, inarray=false) at plpy_typeio.c:1124 #15 0x00007fbd1b80be9d in PLy_output_convert (arg=0x625000177248, val=0x7fbd1afa0770, isnull=0x625000184174) at plpy_typeio.c:122 #16 0x00007fbd1b7e06fd in PLy_exec_function (fcinfo=0x625000184158, proc=0x625000177220) at plpy_exec.c:235 #17 0x00007fbd1b7efa3a in plpython3_call_handler (fcinfo=0x625000184158) at plpy_main.c:247 #18 0x000055eb872ab667 in ExecInterpExpr (state=0x625000184070, econtext=0x625000183d70, isnull=0x7ffdc25d48a0) at execExprInterp.c:727 #19 0x000055eb872a3a4a in ExecInterpExprStillValid (state=0x625000184070, econtext=0x625000183d70, isNull=0x7ffdc25d48a0) at execExprInterp.c:1826 #20 0x000055eb875a34cd in ExecEvalExprSwitchContext (state=0x625000184070, econtext=0x625000183d70, isNull=0x7ffdc25d48a0) at ../../../src/include/executor/executor.h:341 #21 0x000055eb875a3024 in ExecProject (projInfo=0x625000184068) at ../../../src/include/executor/executor.h:375 #22 0x000055eb875a1f5c in ExecResult (pstate=0x625000183c58) at nodeResult.c:136 #23 0x000055eb87376877 in ExecProcNodeFirst (node=0x625000183c58) at execProcnode.c:464 #24 0x000055eb873393a4 in ExecProcNode (node=0x625000183c58) at ../../../src/include/executor/executor.h:259 #25 0x000055eb8731c58c in ExecutePlan (estate=0x625000183a20, planstate=0x625000183c58, use_parallel_mode=false, operation=CMD_SELECT, sendTuples=true, numberTuples=0, direction=ForwardScanDirection, dest=0x625000181968, execute_once=true) at execMain.c:1636 #26 0x000055eb8731bd92 in standard_ExecutorRun (queryDesc=0x6190000015a0, direction=ForwardScanDirection, count=0, execute_once=true) at execMain.c:363 #27 0x000055eb8731adb3 in ExecutorRun (queryDesc=0x6190000015a0, direction=ForwardScanDirection, count=0, execute_once=true) at execMain.c:307 #28 0x000055eb8843a4c9 in PortalRunSelect (portal=0x62500002aa20, forward=true, count=0, dest=0x625000181968) at pquery.c:924 #29 0x000055eb8843887c in PortalRun (portal=0x62500002aa20, count=9223372036854775807, isTopLevel=true, run_once=true, dest=0x625000181968, altdest=0x625000181968, qc=0x7ffdc25d5900) at pquery.c:768 #30 0x000055eb88422fff in exec_simple_query (query_string=0x625000005220 "SELECT test_transform();") at postgres.c:1250 #31 0x000055eb884205c9 in PostgresMain (dbname=0x629000011278 "regression", username=0x629000011258 "law") at postgres.c:4593 #32 0x000055eb87ed06f1 in BackendRun (port=0x615000002b00) at postmaster.c:4511 #33 0x000055eb87ece7f0 in BackendStartup (port=0x615000002b00) at postmaster.c:4239 #34 0x000055eb87ec9c10 in ServerLoop () at postmaster.c:1806 #35 0x000055eb87ec41d7 in PostmasterMain (argc=3, argv=0x6030000006d0) at postmaster.c:1478 #36 0x000055eb8770321b in main (argc=3, argv=0x6030000006d0) at main.c:202 (gdb) frame 12 #12 0x00007fbd6410ed7f in plpython_to_hstore (fcinfo=0x7ffdc25d0460) at hstore_plpython.c:154 154 tuple = PyList_GetItem(items, i); (gdb) print items $1 = (PyObject * volatile) 0x0 Here plpython_to_hstore() has got a string as an argument, but failed to detect that it's not a dictionary. With plpython2 (on REL_14_STABLE) I get: ERROR: not a Python mapping CONTEXT: while creating return value PL/Python function "test_transform" As noted in https://bugs.python.org/issue5945, the behaviour of PyMapping_Check() changed in Python 3, so it can't be used anymore to differentiate real dictionaries from strings or alike. -
Re: BUG #17908: plpython_to_hstore() crashes with a non-dict argument
Dmitry Dolgov <9erthalion6@gmail.com> — 2023-04-27T08:27:27Z
> On Tue, Apr 25, 2023 at 01:00:02PM +0000, PG Bug reporting form wrote: > The following bug has been logged on the website: > > Bug reference: 17908 > Logged by: Alexander Lakhin > Email address: exclusion@gmail.com > PostgreSQL version: 15.2 > Operating system: Ubuntu 22.04 > Description: > > When executing the following query: > CREATE EXTENSION hstore_plpython3u CASCADE; > CREATE FUNCTION test_transform() RETURNS hstore > LANGUAGE plpython3u > TRANSFORM FOR TYPE hstore AS 'return "a"'; > SELECT test_transform(); > > Here plpython_to_hstore() has got a string as an argument, but failed to > detect that it's not a dictionary. > With plpython2 (on REL_14_STABLE) I get: > ERROR: not a Python mapping > CONTEXT: while creating return value > PL/Python function "test_transform" > > As noted in https://bugs.python.org/issue5945, the behaviour of > PyMapping_Check() changed in Python 3, so it can't be used anymore to > differentiate real dictionaries from strings or alike. Thanks for finding this! That's indeed very annoying. After a quick investigation looks like a proposed solution from [1] is to use PyType_HasFeature with Py_TPFLAGS_MAPPING: - if (!PyMapping_Check(dict)) + dict_type = Py_TYPE(dict); + if (!PyType_HasFeature(dict_type, Py_TPFLAGS_MAPPING)) But this flag is available only starting from Python 3.10, so not backward compatible :( [1]: https://bugs.python.org/issue46376 -
Re: BUG #17908: plpython_to_hstore() crashes with a non-dict argument
Tom Lane <tgl@sss.pgh.pa.us> — 2023-04-27T14:46:29Z
Dmitry Dolgov <9erthalion6@gmail.com> writes: >> On Tue, Apr 25, 2023 at 01:00:02PM +0000, PG Bug reporting form wrote: >> As noted in https://bugs.python.org/issue5945, the behaviour of >> PyMapping_Check() changed in Python 3, so it can't be used anymore to >> differentiate real dictionaries from strings or alike. > Thanks for finding this! That's indeed very annoying. Yuck. > After a quick > investigation looks like a proposed solution from [1] is to use > PyType_HasFeature with Py_TPFLAGS_MAPPING: > - if (!PyMapping_Check(dict)) > + dict_type = Py_TYPE(dict); > + if (!PyType_HasFeature(dict_type, Py_TPFLAGS_MAPPING)) > But this flag is available only starting from Python 3.10, so not > backward compatible :( Yeah, doesn't sound hugely workable; I don't think we can require 3.10 yet. The issue5945 discussion suggested >>> And recommend `PyMapping_Check() && !PySequence_Check()` for true mapping test? I haven't verified this but will go test it shortly. If it's true, it would explain why our other uses of PyMapping_Check haven't failed, because (whether by chance or not I dunno) they are not reached if PySequence_Check is true. regards, tom lane