Hello hackers,

I met SIGSEGV when using `array_position()` with record type
arguments, so I've written a patch which corrects this problem. It
seems that `array_position...()` sets wrong memory context for the
cached function (in this case `record_eq()`) which is used to find a
matching element.

The problem is reproducable with the following query.

SELECT array_position(ids, (1, 1))
FROM (VALUES (ARRAY[(0, 0)]), (ARRAY[(1, 1)])) AS _(ids);
From 8868ae0050ec382bc1bae2b993742eb2a40bbb14 Mon Sep 17 00:00:00 2001
From: Junseok Yang <jsy...@bitnine.net>
Date: Thu, 8 Dec 2016 18:25:21 -0800
Subject: [PATCH] Fix memory context bugs in `array_position...()`

When `array_position()` is called with record type arguments, it uses
`record_eq()` to find a matching element. Before calling `record_eq()`,
it stores `FmgrInfo` of `record_eq()` to its `FmgrInfo` as extra data
in the context of `ecxt_per_query_memory`. However, it sets the context
of extra data for `FmgrInfo` of `record_eq()` to `CurrentMemoryContext`
which is `ecxt_per_tuple_memory`. And `record_eq()` also stores extra
data in the context set by `array_position()`. In this scenario, if
`array_position()` is called more than twice over tuples in a query,
the process for this session will be terminated with SIGSEGV because
the extra data for `record_eq()` should be already freed after the
first tuple was processed.

`array_positions()` has the same issue.
---
 src/backend/utils/adt/array_userfuncs.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/backend/utils/adt/array_userfuncs.c b/src/backend/utils/adt/array_userfuncs.c
index 8d6fa41..9eb678a 100644
--- a/src/backend/utils/adt/array_userfuncs.c
+++ b/src/backend/utils/adt/array_userfuncs.c
@@ -795,7 +795,8 @@ array_position_common(FunctionCallInfo fcinfo)
 					   format_type_be(element_type))));
 
 		my_extra->element_type = element_type;
-		fmgr_info(typentry->eq_opr_finfo.fn_oid, &my_extra->proc);
+		fmgr_info_cxt(typentry->eq_opr_finfo.fn_oid, &my_extra->proc,
+					  fcinfo->flinfo->fn_mcxt);
 	}
 
 	/* Examine each array element until we find a match. */
@@ -933,7 +934,8 @@ array_positions(PG_FUNCTION_ARGS)
 					   format_type_be(element_type))));
 
 		my_extra->element_type = element_type;
-		fmgr_info(typentry->eq_opr_finfo.fn_oid, &my_extra->proc);
+		fmgr_info_cxt(typentry->eq_opr_finfo.fn_oid, &my_extra->proc,
+					  fcinfo->flinfo->fn_mcxt);
 	}
 
 	/*
-- 
2.7.4

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to