Skip to content

Commit

Permalink
Fix yet more problems with incorrectly-constructed zero-length arrays.
Browse files Browse the repository at this point in the history
Commit 716ea62 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 716ea62 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
  • Loading branch information
tglsfdc committed Jul 9, 2018
1 parent 6abad00 commit 01783ac
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 3 deletions.
17 changes: 14 additions & 3 deletions contrib/intarray/_int_tool.c
Expand Up @@ -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);

Expand All @@ -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;
Expand All @@ -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);
Expand Down
24 changes: 24 additions & 0 deletions contrib/intarray/expected/_int.out
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions contrib/intarray/sql/_int.sql
Expand Up @@ -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
Expand Down

0 comments on commit 01783ac

Please sign in to comment.