postgres.git / summary / log / commit / refs

commit    01783ac36de1aac9bf8d19f6c2814778188d4523
Author:   Tom Lane <tgl@sss.pgh.pa.us>
Date:     Mon Jul 09 18:28:04 2018 +0000

    Fix yet more problems with incorrectly-constructed zero-length arrays.
    
    Commit 716ea626a attempted to fix the problem of building 1-D zero-size
    arrays once and for all.  But it turns out that contrib/intarray has some
    code that doesn't use construct_array() but just builds arrays by hand,
    so it didn't get the memo.  This appears to affect all of subarray(),
    intset_subtract(), inner_int_union(), inner_int_inter(), and
    intarray_concat_arrays().
    
    Back-patch into v11.  In the past we've not back-patched this type of
    change, but since v11 is still in beta it seems all right to include
    this fix in it.  Besides it's more consistent to make the fix in v11
    where 716ea626a appeared.
    
    Report and patch by Alexey Kryuchkov, some cosmetic adjustments by me
    
    Report: https://postgr.es/m/153053285112.13258.434620894305716755@wrigleys.postgresql.org
    Discussion: https://postgr.es/m/CAN85JcYphDLYt4CpMDLZjjNVqGDrFJ5eS3YF=wLAhFoDQuBsyg@mail.gmail.com


contrib/intarray/_int_tool.c | 17 ++++++++++++++--- contrib/intarray/expected/_int.out | 24 ++++++++++++++++++++++++ contrib/intarray/sql/_int.sql | 4 ++++ 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/contrib/intarray/_int_tool.c b/contrib/intarray/_int_tool.c index ee8fb64a478..d86485dfa5c 100644 --- a/contrib/intarray/_int_tool.c +++ b/contrib/intarray/_int_tool.c @@ -220,7 +220,16 @@ ArrayType * new_intArrayType(int num) { ArrayType *r; - int nbytes = ARR_OVERHEAD_NONULLS(1) + sizeof(int) * num; + int nbytes; + + /* if no elements, return a zero-dimensional array */ + if (num <= 0) + { + r = construct_empty_array(INT4OID); + return r; + } + + nbytes = ARR_OVERHEAD_NONULLS(1) + sizeof(int) * num; r = (ArrayType *) palloc0(nbytes); @@ -237,11 +246,11 @@ new_intArrayType(int num) ArrayType * resize_intArrayType(ArrayType *a, int num) { - int nbytes = ARR_DATA_OFFSET(a) + sizeof(int) * num; + int nbytes; int i; /* if no elements, return a zero-dimensional array */ - if (num == 0) + if (num <= 0) { ARR_NDIM(a) = 0; return a; @@ -250,6 +259,8 @@ resize_intArrayType(ArrayType *a, int num) if (num == ARRNELEMS(a)) return a; + nbytes = ARR_DATA_OFFSET(a) + sizeof(int) * num; + a = (ArrayType *) repalloc(a, nbytes); SET_VARSIZE(a, nbytes); diff --git a/contrib/intarray/expected/_int.out b/contrib/intarray/expected/_int.out index 0a5dd463acb..105c951badf 100644 --- a/contrib/intarray/expected/_int.out +++ b/contrib/intarray/expected/_int.out @@ -151,6 +151,30 @@ SELECT '{-1,3,1}'::int[] & '{1,2}'; {1} (1 row) +SELECT '{1}'::int[] & '{2}'::int[]; + ?column? +---------- + {} +(1 row) + +SELECT array_dims('{1}'::int[] & '{2}'::int[]); + array_dims +------------ + +(1 row) + +SELECT ('{1}'::int[] & '{2}'::int[]) = '{}'::int[]; + ?column? +---------- + t +(1 row) + +SELECT ('{}'::int[] & '{}'::int[]) = '{}'::int[]; + ?column? +---------- + t +(1 row) + --test query_int SELECT '1'::query_int; query_int diff --git a/contrib/intarray/sql/_int.sql b/contrib/intarray/sql/_int.sql index 44e1a729b4f..40225c65abb 100644 --- a/contrib/intarray/sql/_int.sql +++ b/contrib/intarray/sql/_int.sql @@ -30,6 +30,10 @@ SELECT '{123,623,445}'::int[] | 1623; SELECT '{123,623,445}'::int[] | '{1623,623}'; SELECT '{123,623,445}'::int[] & '{1623,623}'; SELECT '{-1,3,1}'::int[] & '{1,2}'; +SELECT '{1}'::int[] & '{2}'::int[]; +SELECT array_dims('{1}'::int[] & '{2}'::int[]); +SELECT ('{1}'::int[] & '{2}'::int[]) = '{}'::int[]; +SELECT ('{}'::int[] & '{}'::int[]) = '{}'::int[]; --test query_int [parent: 6abad00585b7]