From 4573034d05961da16d9f4deb334bea39d620b5e9 Mon Sep 17 00:00:00 2001 From: "Chao Li (Evan)" Date: Mon, 18 May 2026 09:17:55 +0800 Subject: [PATCH v1 1/2] Fix prefix matching of expression stats keys When validating keys in imported expression statistics, the code used strncmp() with the input key length. This allowed an invalid key that was only a prefix of a valid key name to be accepted. Fix this by also checking that the key lengths match before comparing the key contents. Add a regression test to cover the prefix-key case. Author: Chao Li --- src/backend/statistics/extended_stats_funcs.c | 3 ++- src/test/regress/expected/stats_import.out | 14 ++++++++++++++ src/test/regress/sql/stats_import.sql | 9 +++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/backend/statistics/extended_stats_funcs.c b/src/backend/statistics/extended_stats_funcs.c index 70393d3a904..15f131724e9 100644 --- a/src/backend/statistics/extended_stats_funcs.c +++ b/src/backend/statistics/extended_stats_funcs.c @@ -886,7 +886,8 @@ key_in_expr_argnames(JsonbValue *key) Assert(key->type == jbvString); for (int i = 0; i < NUM_ATTRIBUTE_STATS_ELEMS; i++) { - if (strncmp(extexprargname[i], key->val.string.val, key->val.string.len) == 0) + if (strlen(extexprargname[i]) == key->val.string.len && + strncmp(extexprargname[i], key->val.string.val, key->val.string.len) == 0) return true; } return false; diff --git a/src/test/regress/expected/stats_import.out b/src/test/regress/expected/stats_import.out index f421e83e232..d73bc96039f 100644 --- a/src/test/regress/expected/stats_import.out +++ b/src/test/regress/expected/stats_import.out @@ -3256,6 +3256,20 @@ most_common_elems | {-1,0,1,2,3} most_common_elem_freqs | {0.25,0.25,0.5,0.25,0.25,0.25,0.5,0.25} elem_count_histogram | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1.5} +-- bad: exprs param which is a prefix of a valid key name +SELECT pg_catalog.pg_restore_extended_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'statistics_schemaname', 'stats_import', + 'statistics_name', 'test_stat_mcelem', + 'inherited', false, + 'exprs', '[{ "n": "-1" }]'::jsonb); +WARNING: could not import element in expression -1: invalid key name + pg_restore_extended_stats +--------------------------- + f +(1 row) + -- ok: tsvector exceptions, test just the collation exceptions CREATE STATISTICS stats_import.test_stat_tsvec ON (length(name)), (to_tsvector(name)) FROM stats_import.test; SELECT pg_catalog.pg_restore_extended_stats( diff --git a/src/test/regress/sql/stats_import.sql b/src/test/regress/sql/stats_import.sql index c1bf55690a6..b74f6395a5e 100644 --- a/src/test/regress/sql/stats_import.sql +++ b/src/test/regress/sql/stats_import.sql @@ -2244,6 +2244,15 @@ WHERE e.statistics_schemaname = 'stats_import' AND e.inherited = false \gx +-- bad: exprs param which is a prefix of a valid key name +SELECT pg_catalog.pg_restore_extended_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'statistics_schemaname', 'stats_import', + 'statistics_name', 'test_stat_mcelem', + 'inherited', false, + 'exprs', '[{ "n": "-1" }]'::jsonb); + -- ok: tsvector exceptions, test just the collation exceptions CREATE STATISTICS stats_import.test_stat_tsvec ON (length(name)), (to_tsvector(name)) FROM stats_import.test; SELECT pg_catalog.pg_restore_extended_stats( -- 2.50.1 (Apple Git-155)