From 4fe8ba63fe472328019e1c43083f8ba3fd09656f Mon Sep 17 00:00:00 2001
From: Teodor Sigaev <teodor@sigaev.ru>
Date: Tue, 11 Jul 2006 16:00:44 +0000
Subject: [PATCH] Fix bug corrupting query in gist consistent function. Thank
 to Mario Weilguni <mweilguni@sime.com> to discover a bug.

---
 contrib/ltree/_ltree_gist.c |  1 +
 contrib/ltree/ltree.h       |  5 ++++-
 contrib/ltree/ltree_gist.c  | 16 ++++++++++++++--
 3 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/contrib/ltree/_ltree_gist.c b/contrib/ltree/_ltree_gist.c
index 285077802bb..30bf2e02964 100644
--- a/contrib/ltree/_ltree_gist.c
+++ b/contrib/ltree/_ltree_gist.c
@@ -580,5 +580,6 @@ _ltree_consistent(PG_FUNCTION_ARGS)
 			/* internal error */
 			elog(ERROR, "unrecognized StrategyNumber: %d", strategy);
 	}
+	PG_FREE_IF_COPY(query,1);
 	PG_RETURN_BOOL(res);
 }
diff --git a/contrib/ltree/ltree.h b/contrib/ltree/ltree.h
index 3cd67794b9b..b9058d5edff 100644
--- a/contrib/ltree/ltree.h
+++ b/contrib/ltree/ltree.h
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/contrib/ltree/ltree.h,v 1.15 2006/03/11 04:38:29 momjian Exp $ */
+/* $PostgreSQL: pgsql/contrib/ltree/ltree.h,v 1.16 2006/07/11 16:00:44 teodor Exp $ */
 
 #ifndef __LTREE_H__
 #define __LTREE_H__
@@ -163,8 +163,11 @@ bool compare_subnode(ltree_level * t, char *q, int len,
 ltree	   *lca_inner(ltree ** a, int len);
 
 #define PG_GETARG_LTREE(x)	((ltree*)DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(x))))
+#define PG_GETARG_LTREE_COPY(x)	((ltree*)DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(x))))
 #define PG_GETARG_LQUERY(x) ((lquery*)DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(x))))
+#define PG_GETARG_LQUERY_COPY(x) ((lquery*)DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(x))))
 #define PG_GETARG_LTXTQUERY(x) ((ltxtquery*)DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(x))))
+#define PG_GETARG_LTXTQUERY_COPY(x) ((ltxtquery*)DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(x))))
 
 /* GiST support for ltree */
 
diff --git a/contrib/ltree/ltree_gist.c b/contrib/ltree/ltree_gist.c
index f5214b746b1..d63b25f2cdf 100644
--- a/contrib/ltree/ltree_gist.c
+++ b/contrib/ltree/ltree_gist.c
@@ -1,7 +1,7 @@
 /*
  * GiST support for ltree
  * Teodor Sigaev <teodor@stack.net>
- * $PostgreSQL: pgsql/contrib/ltree/ltree_gist.c,v 1.15 2006/06/28 11:59:59 teodor Exp $
+ * $PostgreSQL: pgsql/contrib/ltree/ltree_gist.c,v 1.16 2006/07/11 16:00:44 teodor Exp $
  */
 
 #include "ltree.h"
@@ -627,7 +627,7 @@ Datum
 ltree_consistent(PG_FUNCTION_ARGS)
 {
 	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
-	char	   *query = (char *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(1)));
+	void	   *query = NULL;
 	ltree_gist *key = (ltree_gist *) DatumGetPointer(entry->key);
 	StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
 	bool		res = false;
@@ -635,15 +635,18 @@ ltree_consistent(PG_FUNCTION_ARGS)
 	switch (strategy)
 	{
 		case BTLessStrategyNumber:
+			query = PG_GETARG_LTREE(1);
 			res = (GIST_LEAF(entry)) ?
 				(ltree_compare((ltree *) query, LTG_NODE(key)) > 0)
 				:
 				(ltree_compare((ltree *) query, LTG_GETLNODE(key)) >= 0);
 			break;
 		case BTLessEqualStrategyNumber:
+			query = PG_GETARG_LTREE(1);
 			res = (ltree_compare((ltree *) query, LTG_GETLNODE(key)) >= 0);
 			break;
 		case BTEqualStrategyNumber:
+			query = PG_GETARG_LTREE(1);
 			if (GIST_LEAF(entry))
 				res = (ltree_compare((ltree *) query, LTG_NODE(key)) == 0);
 			else
@@ -654,21 +657,25 @@ ltree_consistent(PG_FUNCTION_ARGS)
 					);
 			break;
 		case BTGreaterEqualStrategyNumber:
+			query = PG_GETARG_LTREE(1);
 			res = (ltree_compare((ltree *) query, LTG_GETRNODE(key)) <= 0);
 			break;
 		case BTGreaterStrategyNumber:
+			query = PG_GETARG_LTREE(1);
 			res = (GIST_LEAF(entry)) ?
 				(ltree_compare((ltree *) query, LTG_GETRNODE(key)) < 0)
 				:
 				(ltree_compare((ltree *) query, LTG_GETRNODE(key)) <= 0);
 			break;
 		case 10:
+			query = PG_GETARG_LTREE_COPY(1);
 			res = (GIST_LEAF(entry)) ?
 				inner_isparent((ltree *) query, LTG_NODE(key))
 				:
 				gist_isparent(key, (ltree *) query);
 			break;
 		case 11:
+			query = PG_GETARG_LTREE_COPY(1);
 			res = (GIST_LEAF(entry)) ?
 				inner_isparent(LTG_NODE(key), (ltree *) query)
 				:
@@ -676,6 +683,7 @@ ltree_consistent(PG_FUNCTION_ARGS)
 			break;
 		case 12:
 		case 13:
+			query = PG_GETARG_LQUERY(1);
 			if (GIST_LEAF(entry))
 				res = DatumGetBool(DirectFunctionCall2(ltq_regex,
 											  PointerGetDatum(LTG_NODE(key)),
@@ -686,6 +694,7 @@ ltree_consistent(PG_FUNCTION_ARGS)
 			break;
 		case 14:
 		case 15:
+			query = PG_GETARG_LQUERY(1);
 			if (GIST_LEAF(entry))
 				res = DatumGetBool(DirectFunctionCall2(ltxtq_exec,
 											  PointerGetDatum(LTG_NODE(key)),
@@ -696,6 +705,7 @@ ltree_consistent(PG_FUNCTION_ARGS)
 			break;
 		case 16:
 		case 17:
+			query = DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(1)));
 			if (GIST_LEAF(entry))
 				res = DatumGetBool(DirectFunctionCall2(lt_q_regex,
 											  PointerGetDatum(LTG_NODE(key)),
@@ -708,5 +718,7 @@ ltree_consistent(PG_FUNCTION_ARGS)
 			/* internal error */
 			elog(ERROR, "unrecognized StrategyNumber: %d", strategy);
 	}
+
+	PG_FREE_IF_COPY(query,1);
 	PG_RETURN_BOOL(res);
 }
-- 
GitLab