public inbox for [email protected]  
help / color / mirror / Atom feed
BUG #19492: intarray: fix variable stats leak in _int_matchsel
3+ messages / 3 participants
[nested] [flat]

* BUG #19492: intarray: fix variable stats leak in _int_matchsel
@ 2026-05-24 05:13 PG Bug reporting form <[email protected]>
  2026-05-24 05:15 ` Re:BUG #19492: intarray: fix variable stats leak in _int_matchsel =?gb18030?B?emVuZ21hbg==?= <[email protected]>
  0 siblings, 1 reply; 3+ messages in thread

From: PG Bug reporting form @ 2026-05-24 05:13 UTC (permalink / raw)
  To: [email protected]; +Cc: [email protected]

The following bug has been logged on the website:

Bug reference:      19492
Logged by:          Man Zeng
Email address:      [email protected]
PostgreSQL version: 18.4
Operating system:   24.04.1-Ubuntu
Description:        

Hi all,

While investigating the intarray contrib module, I noticed a variable
stats leak in _int_matchsel().

When vardata.vartype != INT4ARRAYOID, the function returns
DEFAULT_EQ_SEL early without releasing the variable stats previously
acquired via examine_variable(). This causes a memory leak in the
current memory context.

The fix is straightforward: add ReleaseVariableStats(vardata) before
the early return.

Steps to reproduce:
```sql
postgres@zxm-VMware-Virtual-Platform:~/code/postgres/contrib$ psql
psql (19devel)
Type "help" for help.

postgres=# CREATE EXTENSION intarray;
CREATE EXTENSION
postgres=# CREATE OR REPLACE FUNCTION my_text_eq(a text, b text) RETURNS
boolean AS $$
BEGIN
    RETURN a = b;
END;
$$ LANGUAGE plpgsql;
CREATE FUNCTION
postgres=# CREATE OPERATOR %% (
    LEFTARG = text,
    RIGHTARG = text,
    FUNCTION = my_text_eq,
    RESTRICT = _int_matchsel
);
CREATE OPERATOR
postgres=# CREATE TEMP TABLE test_vuln (t text);
CREATE TABLE
postgres=# INSERT INTO test_vuln SELECT md5(i::text) FROM generate_series(1,
1000) i;
ANALYZE test_vuln;
INSERT 0 1000
ANALYZE
postgres=# EXPLAIN (COSTS ON) SELECT * FROM test_vuln WHERE t %%
'test'::text;
2026-05-20 23:47:42.257 CST [11370] WARNING:  resource was not closed: cache
pg_statistic (73), tuple 9/33 has count 1
WARNING:  resource was not closed: cache pg_statistic (73), tuple 9/33 has
count 1
                         QUERY PLAN
------------------------------------------------------------
 Seq Scan on test_vuln  (cost=0.00..269.00 rows=5 width=33)
   Filter: (t %% 'test'::text)
(2 rows)

postgres=#
```

SQL:
```sql
CREATE EXTENSION intarray;
CREATE OR REPLACE FUNCTION my_text_eq(a text, b text) RETURNS boolean AS $$
BEGIN
    RETURN a = b;
END;
$$ LANGUAGE plpgsql;
CREATE OPERATOR %% (
    LEFTARG = text,
    RIGHTARG = text,
    FUNCTION = my_text_eq,
    RESTRICT = _int_matchsel
);
CREATE TEMP TABLE test_vuln (t text);
INSERT INTO test_vuln SELECT md5(i::text) FROM generate_series(1, 1000) i;
ANALYZE test_vuln;
EXPLAIN (COSTS ON) SELECT * FROM test_vuln WHERE t %% 'test'::text;
```

Regards,
Man Zeng







^ permalink  raw  reply  [nested|flat] 3+ messages in thread

* Re:BUG #19492: intarray: fix variable stats leak in _int_matchsel
  2026-05-24 05:13 BUG #19492: intarray: fix variable stats leak in _int_matchsel PG Bug reporting form <[email protected]>
@ 2026-05-24 05:15 ` =?gb18030?B?emVuZ21hbg==?= <[email protected]>
  2026-05-25 22:17   ` Re: BUG #19492: intarray: fix variable stats leak in _int_matchsel Tom Lane <[email protected]>
  0 siblings, 1 reply; 3+ messages in thread

From: =?gb18030?B?emVuZ21hbg==?= @ 2026-05-24 05:15 UTC (permalink / raw)
  To: =?gb18030?B?1PjC+g==?= <[email protected]>; =?gb18030?B?cGdzcWwtYnVncw==?= <[email protected]>

Patch attached. Also added a test case that exercises this code path
by creating a text operator with _int_matchsel as the restriction
estimator.

Regards,
Man Zeng

Attachments:

  [application/octet-stream] 0001-Fix-variable-stats-leak-in-_int_matchsel-early-retur.patch (2.7K, 2-0001-Fix-variable-stats-leak-in-_int_matchsel-early-retur.patch)
  download | inline diff:
From 8e5606371df544f8be48937419fe54c96a358048 Mon Sep 17 00:00:00 2001
From: Man Zeng <[email protected]>
Date: Sun, 24 May 2026 12:36:36 +0800
Subject: [PATCH] Fix variable stats leak in _int_matchsel early return path

When vardata.vartype != INT4ARRAYOID, _int_matchsel returns
DEFAULT_EQ_SEL without releasing the variable stats previously
acquired via examine_variable(), causing a memory leak. Add the
missing ReleaseVariableStats() call.
---
 contrib/intarray/_int_selfuncs.c   |  3 +++
 contrib/intarray/expected/_int.out | 21 +++++++++++++++++++++
 contrib/intarray/sql/_int.sql      | 20 ++++++++++++++++++++
 3 files changed, 44 insertions(+)

diff --git a/contrib/intarray/_int_selfuncs.c b/contrib/intarray/_int_selfuncs.c
index 7fce743632f..c0161928074 100644
--- a/contrib/intarray/_int_selfuncs.c
+++ b/contrib/intarray/_int_selfuncs.c
@@ -151,7 +151,10 @@ _int_matchsel(PG_FUNCTION_ARGS)
 	 * query_int.
 	 */
 	if (vardata.vartype != INT4ARRAYOID)
+	{
+		ReleaseVariableStats(vardata);
 		PG_RETURN_FLOAT8(DEFAULT_EQ_SEL);
+	}
 
 	/*
 	 * Can't do anything useful if the something is not a constant, either.
diff --git a/contrib/intarray/expected/_int.out b/contrib/intarray/expected/_int.out
index fb4086a95ca..8ae730a535d 100644
--- a/contrib/intarray/expected/_int.out
+++ b/contrib/intarray/expected/_int.out
@@ -1026,3 +1026,24 @@ SELECT count(*) from test__int WHERE a @@ '!2733 & (2738 | 254)';
 (1 row)
 
 RESET enable_seqscan;
+CREATE OR REPLACE FUNCTION my_text_eq(a text, b text) RETURNS boolean AS $$
+BEGIN
+    RETURN a = b;
+END;
+$$ LANGUAGE plpgsql;
+CREATE OPERATOR %% (
+    LEFTARG = text,
+    RIGHTARG = text,
+    FUNCTION = my_text_eq,
+    RESTRICT = _int_matchsel
+);
+CREATE TEMP TABLE test_vuln (t text);
+INSERT INTO test_vuln SELECT md5(i::text) FROM generate_series(1, 1000) i;
+ANALYZE test_vuln;
+SELECT * FROM test_vuln WHERE t %% 'test'::text;
+ t 
+---
+(0 rows)
+
+DROP FUNCTION my_text_eq CASCADE;
+NOTICE:  drop cascades to operator %%(text,text)
diff --git a/contrib/intarray/sql/_int.sql b/contrib/intarray/sql/_int.sql
index 0d30914725e..765b1138772 100644
--- a/contrib/intarray/sql/_int.sql
+++ b/contrib/intarray/sql/_int.sql
@@ -252,3 +252,23 @@ SELECT count(*) from test__int WHERE a @@ '!2733 & (2738 | 254)';
 
 
 RESET enable_seqscan;
+
+CREATE OR REPLACE FUNCTION my_text_eq(a text, b text) RETURNS boolean AS $$
+BEGIN
+    RETURN a = b;
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE OPERATOR %% (
+    LEFTARG = text,
+    RIGHTARG = text,
+    FUNCTION = my_text_eq,
+    RESTRICT = _int_matchsel
+);
+
+CREATE TEMP TABLE test_vuln (t text);
+INSERT INTO test_vuln SELECT md5(i::text) FROM generate_series(1, 1000) i;
+ANALYZE test_vuln;
+
+SELECT * FROM test_vuln WHERE t %% 'test'::text;
+DROP FUNCTION my_text_eq CASCADE;
-- 
2.45.2



^ permalink  raw  reply  [nested|flat] 3+ messages in thread

* Re: BUG #19492: intarray: fix variable stats leak in _int_matchsel
  2026-05-24 05:13 BUG #19492: intarray: fix variable stats leak in _int_matchsel PG Bug reporting form <[email protected]>
  2026-05-24 05:15 ` Re:BUG #19492: intarray: fix variable stats leak in _int_matchsel =?gb18030?B?emVuZ21hbg==?= <[email protected]>
@ 2026-05-25 22:17   ` Tom Lane <[email protected]>
  0 siblings, 0 replies; 3+ messages in thread

From: Tom Lane @ 2026-05-25 22:17 UTC (permalink / raw)
  To: =?gb18030?B?emVuZ21hbg==?= <[email protected]>; +Cc: =?gb18030?B?cGdzcWwtYnVncw==?= <[email protected]>

"=?gb18030?B?emVuZ21hbg==?=" <[email protected]> writes:
> Patch attached. Also added a test case that exercises this code path
> by creating a text operator with _int_matchsel as the restriction
> estimator.

Good catch, pushed.  I didn't bother with the test case though ---
none of the other early exits in that function have test cases,
and I don't see why this one is any more fragile than the others.

			regards, tom lane






^ permalink  raw  reply  [nested|flat] 3+ messages in thread


end of thread, other threads:[~2026-05-25 22:17 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2026-05-24 05:13 BUG #19492: intarray: fix variable stats leak in _int_matchsel PG Bug reporting form <[email protected]>
2026-05-24 05:15 ` =?gb18030?B?emVuZ21hbg==?= <[email protected]>
2026-05-25 22:17   ` Tom Lane <[email protected]>

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox