From 95cce84c16ca9d1477ef9e2d35bb688173142461 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 9 Jul 2018 14:28:04 -0400 Subject: [PATCH] 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 ee8fb64a47..d86485dfa5 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 0a5dd463ac..105c951bad 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 44e1a729b4..40225c65ab 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 -- 2.40.0