From e66197fa2efa8ae0cab1eed6b2257ab4e2134b1e Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Tue, 8 Mar 2016 13:33:24 -0800 Subject: [PATCH] plperl: Correctly handle empty arrays in plperl_ref_from_pg_array. plperl_ref_from_pg_array() didn't consider the case that postgrs arrays can have 0 dimensions (when they're empty) and accessed the first dimension without a check. Fix that by special casing the empty array case. Author: Alex Hunsaker Reported-By: Andres Freund / valgrind / buildfarm animal skink Discussion: 20160308063240.usnzg6bsbjrne667@alap3.anarazel.de Backpatch: 9.1- --- src/pl/plperl/plperl.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c index b35ef3f64b..cd917ab8e4 100644 --- a/src/pl/plperl/plperl.c +++ b/src/pl/plperl/plperl.c @@ -1450,17 +1450,25 @@ plperl_ref_from_pg_array(Datum arg, Oid typid) info->ndims = ARR_NDIM(ar); dims = ARR_DIMS(ar); - deconstruct_array(ar, elementtype, typlen, typbyval, - typalign, &info->elements, &info->nulls, - &nitems); + /* No dimensions? Return an empty array */ + if (info->ndims == 0) + { + av = newRV_noinc((SV *) newAV()); + } + else + { + deconstruct_array(ar, elementtype, typlen, typbyval, + typalign, &info->elements, &info->nulls, + &nitems); - /* Get total number of elements in each dimension */ - info->nelems = palloc(sizeof(int) * info->ndims); - info->nelems[0] = nitems; - for (i = 1; i < info->ndims; i++) - info->nelems[i] = info->nelems[i - 1] / dims[i - 1]; + /* Get total number of elements in each dimension */ + info->nelems = palloc(sizeof(int) * info->ndims); + info->nelems[0] = nitems; + for (i = 1; i < info->ndims; i++) + info->nelems[i] = info->nelems[i - 1] / dims[i - 1]; - av = split_array(info, 0, nitems, 0); + av = split_array(info, 0, nitems, 0); + } hv = newHV(); (void) hv_store(hv, "array", 5, av, 0); @@ -1479,6 +1487,9 @@ split_array(plperl_array_info *info, int first, int last, int nest) int i; AV *result; + /* we should only be called when we have something to split */ + Assert(info->ndims > 0); + /* since this function recurses, it could be driven to stack overflow */ check_stack_depth();