Skip to content

Commit a1d9aac

Browse files
committed
Handle zero-length sublist correctly in Python -> SQL array conversion.
If PLySequence_ToArray came across a zero-length sublist, it'd compute the overall array size as zero, possibly leading to a memory clobber. (This would likely qualify as a security bug, were it not that plpython is an untrusted language already.) I think there are other corner-case issues in this code as well, notably that the error messages don't match the core code and for some ranges of array sizes you'd get "invalid memory alloc request size" rather than the intended message about array size. Really this code has no business doing its own array size calculation at all, so remove the faulty code in favor of using ArrayGetNItems(). Per bug #17912 from Alexander Lakhin. Bug seems to have come in with commit 94aceed, so back-patch to all supported branches. Discussion: https://postgr.es/m/17912-82ceed78731d9cdc@postgresql.org
1 parent d29eba1 commit a1d9aac

File tree

4 files changed

+32
-16
lines changed

4 files changed

+32
-16
lines changed

src/pl/plpython/expected/plpython_types.out

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,15 @@ SELECT * FROM test_type_conversion_array_mixed2();
687687
ERROR: invalid input syntax for type integer: "abc"
688688
CONTEXT: while creating return value
689689
PL/Python function "test_type_conversion_array_mixed2"
690+
CREATE FUNCTION test_type_conversion_array_mixed3() RETURNS text[] AS $$
691+
return [[], 'a']
692+
$$ LANGUAGE plpythonu;
693+
SELECT * FROM test_type_conversion_array_mixed3();
694+
test_type_conversion_array_mixed3
695+
-----------------------------------
696+
{[],a}
697+
(1 row)
698+
690699
CREATE FUNCTION test_type_conversion_mdarray_malformed() RETURNS int[] AS $$
691700
return [[1,2,3],[4,5]]
692701
$$ LANGUAGE plpythonu;

src/pl/plpython/expected/plpython_types_3.out

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,15 @@ SELECT * FROM test_type_conversion_array_mixed2();
687687
ERROR: invalid input syntax for type integer: "abc"
688688
CONTEXT: while creating return value
689689
PL/Python function "test_type_conversion_array_mixed2"
690+
CREATE FUNCTION test_type_conversion_array_mixed3() RETURNS text[] AS $$
691+
return [[], 'a']
692+
$$ LANGUAGE plpython3u;
693+
SELECT * FROM test_type_conversion_array_mixed3();
694+
test_type_conversion_array_mixed3
695+
-----------------------------------
696+
{[],a}
697+
(1 row)
698+
690699
CREATE FUNCTION test_type_conversion_mdarray_malformed() RETURNS int[] AS $$
691700
return [[1,2,3],[4,5]]
692701
$$ LANGUAGE plpython3u;

src/pl/plpython/plpy_typeio.c

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1144,7 +1144,7 @@ PLySequence_ToArray(PLyObToDatum *arg, PyObject *plrv,
11441144
int i;
11451145
Datum *elems;
11461146
bool *nulls;
1147-
int64 len;
1147+
int len;
11481148
int ndim;
11491149
int dims[MAXDIM];
11501150
int lbs[MAXDIM];
@@ -1163,7 +1163,6 @@ PLySequence_ToArray(PLyObToDatum *arg, PyObject *plrv,
11631163
* Determine the number of dimensions, and their sizes.
11641164
*/
11651165
ndim = 0;
1166-
len = 1;
11671166

11681167
Py_INCREF(plrv);
11691168

@@ -1182,17 +1181,6 @@ PLySequence_ToArray(PLyObToDatum *arg, PyObject *plrv,
11821181
if (dims[ndim] < 0)
11831182
PLy_elog(ERROR, "could not determine sequence length for function return value");
11841183

1185-
if (dims[ndim] > MaxAllocSize)
1186-
ereport(ERROR,
1187-
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1188-
errmsg("array size exceeds the maximum allowed")));
1189-
1190-
len *= dims[ndim];
1191-
if (len > MaxAllocSize)
1192-
ereport(ERROR,
1193-
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1194-
errmsg("array size exceeds the maximum allowed")));
1195-
11961184
if (dims[ndim] == 0)
11971185
{
11981186
/* empty sequence */
@@ -1222,15 +1210,18 @@ PLySequence_ToArray(PLyObToDatum *arg, PyObject *plrv,
12221210
errmsg("return value of function with array return type is not a Python sequence")));
12231211

12241212
ndim = 1;
1225-
len = dims[0] = PySequence_Length(plrv);
1213+
dims[0] = PySequence_Length(plrv);
12261214
}
12271215

1216+
/* Allocate space for work arrays, after detecting array size overflow */
1217+
len = ArrayGetNItems(ndim, dims);
1218+
elems = palloc(sizeof(Datum) * len);
1219+
nulls = palloc(sizeof(bool) * len);
1220+
12281221
/*
12291222
* Traverse the Python lists, in depth-first order, and collect all the
12301223
* elements at the bottom level into 'elems'/'nulls' arrays.
12311224
*/
1232-
elems = palloc(sizeof(Datum) * len);
1233-
nulls = palloc(sizeof(bool) * len);
12341225
currelem = 0;
12351226
PLySequence_ToArray_recurse(arg->u.array.elm, plrv,
12361227
dims, ndim, 0,

src/pl/plpython/sql/plpython_types.sql

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,13 @@ $$ LANGUAGE plpythonu;
328328

329329
SELECT * FROM test_type_conversion_array_mixed2();
330330

331+
CREATE FUNCTION test_type_conversion_array_mixed3() RETURNS text[] AS $$
332+
return [[], 'a']
333+
$$ LANGUAGE plpythonu;
334+
335+
SELECT * FROM test_type_conversion_array_mixed3();
336+
337+
331338
CREATE FUNCTION test_type_conversion_mdarray_malformed() RETURNS int[] AS $$
332339
return [[1,2,3],[4,5]]
333340
$$ LANGUAGE plpythonu;

0 commit comments

Comments
 (0)