]> granicus.if.org Git - postgresql/commitdiff
Fix yet more problems with incorrectly-constructed zero-length arrays.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 9 Jul 2018 18:28:04 +0000 (14:28 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 9 Jul 2018 18:28:04 +0000 (14:28 -0400)
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
contrib/intarray/expected/_int.out
contrib/intarray/sql/_int.sql

index ee8fb64a4782f92557ce066c0d5f117832b7ba0f..d86485dfa5c6d35a3c5598716829aded7f929f62 100644 (file)
@@ -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);
index 0a5dd463acb087180fa64a0d45c3bb2f39fc3d15..105c951badf9c7c034624eb5b323d18a28e6190e 100644 (file)
@@ -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 
index 44e1a729b4f0dbf29d8b829d0b6c96b00897457e..40225c65abbfc9c0b9d1dce5074b1754121390a2 100644 (file)
@@ -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