Commit cd331e4b authored by Tom Lane's avatar Tom Lane

Defend against possible crash if a plpython function does not specify names

for its arguments.  Also add a regression test, since someone apparently
changed every single plpython test case to use only named parameters; else
we'd have noticed this sooner.

Euler Taveira de Oliveira, per a report from Alvaro
parent aa38153d
...@@ -357,8 +357,11 @@ CREATE FUNCTION test_return_none() RETURNS int AS $$ ...@@ -357,8 +357,11 @@ CREATE FUNCTION test_return_none() RETURNS int AS $$
None None
$$ LANGUAGE plpythonu; $$ LANGUAGE plpythonu;
-- --
-- Test named parameters -- Test named and nameless parameters
-- --
CREATE FUNCTION test_param_names0(integer, integer) RETURNS int AS $$
return args[0] + args[1]
$$ LANGUAGE plpythonu;
CREATE FUNCTION test_param_names1(a0 integer, a1 text) RETURNS boolean AS $$ CREATE FUNCTION test_param_names1(a0 integer, a1 text) RETURNS boolean AS $$
assert a0 == args[0] assert a0 == args[0]
assert a1 == args[1] assert a1 == args[1]
......
...@@ -197,7 +197,13 @@ SELECT test_return_none(), test_return_none() IS NULL AS "is null"; ...@@ -197,7 +197,13 @@ SELECT test_return_none(), test_return_none() IS NULL AS "is null";
| t | t
(1 row) (1 row)
-- Test for functions with named parameters -- Test for functions with named and nameless parameters
SELECT test_param_names0(2,7);
test_param_names0
-------------------
9
(1 row)
SELECT test_param_names1(1,'text'); SELECT test_param_names1(1,'text');
test_param_names1 test_param_names1
------------------- -------------------
......
/********************************************************************** /**********************************************************************
* plpython.c - python as a procedural language for PostgreSQL * plpython.c - python as a procedural language for PostgreSQL
* *
* $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.119 2009/03/26 22:26:08 petere Exp $ * $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.120 2009/04/03 16:59:42 tgl Exp $
* *
********************************************************************* *********************************************************************
*/ */
...@@ -1052,9 +1052,11 @@ PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure * proc) ...@@ -1052,9 +1052,11 @@ PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure * proc)
arg = Py_None; arg = Py_None;
} }
if (PyList_SetItem(args, i, arg) == -1 || if (PyList_SetItem(args, i, arg) == -1)
(proc->argnames && PLy_elog(ERROR, "PyList_SetItem() failed for PL/Python function \"%s\" while setting up arguments", proc->proname);
PyDict_SetItemString(proc->globals, proc->argnames[i], arg) == -1))
if (proc->argnames && proc->argnames[i] &&
PyDict_SetItemString(proc->globals, proc->argnames[i], arg) == -1)
PLy_elog(ERROR, "PyDict_SetItemString() failed for PL/Python function \"%s\" while setting up arguments", proc->proname); PLy_elog(ERROR, "PyDict_SetItemString() failed for PL/Python function \"%s\" while setting up arguments", proc->proname);
arg = NULL; arg = NULL;
} }
...@@ -1081,7 +1083,8 @@ PLy_function_delete_args(PLyProcedure * proc) ...@@ -1081,7 +1083,8 @@ PLy_function_delete_args(PLyProcedure * proc)
return; return;
for (i = 0; i < proc->nargs; i++) for (i = 0; i < proc->nargs; i++)
PyDict_DelItemString(proc->globals, proc->argnames[i]); if (proc->argnames[i])
PyDict_DelItemString(proc->globals, proc->argnames[i]);
} }
......
...@@ -391,8 +391,12 @@ $$ LANGUAGE plpythonu; ...@@ -391,8 +391,12 @@ $$ LANGUAGE plpythonu;
-- --
-- Test named parameters -- Test named and nameless parameters
-- --
CREATE FUNCTION test_param_names0(integer, integer) RETURNS int AS $$
return args[0] + args[1]
$$ LANGUAGE plpythonu;
CREATE FUNCTION test_param_names1(a0 integer, a1 text) RETURNS boolean AS $$ CREATE FUNCTION test_param_names1(a0 integer, a1 text) RETURNS boolean AS $$
assert a0 == args[0] assert a0 == args[0]
assert a1 == args[1] assert a1 == args[1]
......
...@@ -74,7 +74,8 @@ SELECT test_void_func1(), test_void_func1() IS NULL AS "is null"; ...@@ -74,7 +74,8 @@ SELECT test_void_func1(), test_void_func1() IS NULL AS "is null";
SELECT test_void_func2(); -- should fail SELECT test_void_func2(); -- should fail
SELECT test_return_none(), test_return_none() IS NULL AS "is null"; SELECT test_return_none(), test_return_none() IS NULL AS "is null";
-- Test for functions with named parameters -- Test for functions with named and nameless parameters
SELECT test_param_names0(2,7);
SELECT test_param_names1(1,'text'); SELECT test_param_names1(1,'text');
SELECT test_param_names2(users) from users; SELECT test_param_names2(users) from users;
SELECT test_param_names3(1); SELECT test_param_names3(1);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment