From f559846a68df902715d05579c800f836b8f7226b Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Thu, 16 Feb 2012 20:00:23 -0500
Subject: [PATCH] Fix longstanding error in contrib/intarray's int[] & int[]
 operator.

The array intersection code would give wrong results if the first entry of
the correct output array would be "1".  (I think only this value could be
at risk, since the previous word would always be a lower-bound entry with
that fixed value.)

Problem spotted by Julien Rouhaud, initial patch by Guillaume Lelarge,
cosmetic improvements by me.
---
 contrib/intarray/_int_tool.c       | 15 +++++++++------
 contrib/intarray/expected/_int.out |  6 ++++++
 contrib/intarray/sql/_int.sql      |  1 +
 3 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/contrib/intarray/_int_tool.c b/contrib/intarray/_int_tool.c
index 8c0ec29c31..780b28bc3f 100644
--- a/contrib/intarray/_int_tool.c
+++ b/contrib/intarray/_int_tool.c
@@ -146,7 +146,8 @@ inner_int_inter(ArrayType *a, ArrayType *b)
 			   *db,
 			   *dr;
 	int			i,
-				j;
+				j,
+				k;
 
 	CHECKARRVALID(a);
 	CHECKARRVALID(b);
@@ -161,27 +162,29 @@ inner_int_inter(ArrayType *a, ArrayType *b)
 	r = new_intArrayType(Min(na, nb));
 	dr = ARRPTR(r);
 
-	i = j = 0;
+	i = j = k = 0;
 	while (i < na && j < nb)
+	{
 		if (da[i] < db[j])
 			i++;
 		else if (da[i] == db[j])
 		{
-			if (i + j == 0 || (i + j > 0 && *(dr - 1) != db[j]))
-				*dr++ = db[j];
+			if (k == 0 || dr[k - 1] != db[j])
+				dr[k++] = db[j];
 			i++;
 			j++;
 		}
 		else
 			j++;
+	}
 
-	if ((dr - ARRPTR(r)) == 0)
+	if (k == 0)
 	{
 		pfree(r);
 		return new_intArrayType(0);
 	}
 	else
-		return resize_intArrayType(r, dr - ARRPTR(r));
+		return resize_intArrayType(r, k);
 }
 
 void
diff --git a/contrib/intarray/expected/_int.out b/contrib/intarray/expected/_int.out
index 596439d314..ab28ad33de 100644
--- a/contrib/intarray/expected/_int.out
+++ b/contrib/intarray/expected/_int.out
@@ -143,6 +143,12 @@ SELECT '{123,623,445}'::int[] & '{1623,623}';
  {623}
 (1 row)
 
+SELECT '{-1,3,1}'::int[] & '{1,2}';
+ ?column? 
+----------
+ {1}
+(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 1588e3b514..d020c5fa8e 100644
--- a/contrib/intarray/sql/_int.sql
+++ b/contrib/intarray/sql/_int.sql
@@ -32,6 +32,7 @@ SELECT '{123,623,445}'::int[] | 623;
 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}';
 
 
 --test query_int
-- 
2.49.0