0001-Fix-variable-stats-leak-in-_int_matchsel-early-retur.patch
application/octet-stream
Filename: 0001-Fix-variable-stats-leak-in-_int_matchsel-early-retur.patch
Type: application/octet-stream
Part: 0
Patch
Format: format-patch
Series: patch 0001
Subject: Fix variable stats leak in _int_matchsel early return path
| File | + | − |
|---|---|---|
| contrib/intarray/expected/_int.out | 21 | 0 |
| contrib/intarray/_int_selfuncs.c | 3 | 0 |
| contrib/intarray/sql/_int.sql | 20 | 0 |
From 8e5606371df544f8be48937419fe54c96a358048 Mon Sep 17 00:00:00 2001
From: Man Zeng <zengman@halodbtech.com>
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