| From: | Ewan Young <kdbase(dot)hack(at)gmail(dot)com> |
|---|---|
| To: | PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org> |
| Cc: | Michael Paquier <michael(at)paquier(dot)xyz> |
| Subject: | [PATCH] pg_restore_extended_stats() can store an MCV list that cannot be read back |
| Date: | 2026-06-16 03:15:46 |
| Message-ID: | CAON2xHORd2ESXm1KcVeeZ0Kd_aJk4dL4M2WLtzVDM4puaZ-20w@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
Hi,
pg_restore_extended_stats() does not bound the number of items in an
imported MCV list, but the read path rejects any list with more than
STATS_MCVLIST_MAX_ITEMS (= 10000) items. So an oversized list imports
successfully, gets written to pg_statistic_ext_data, and then makes
every read of that statistics object fail.
Reproduction (current master):
CREATE TABLE t (a int, b int);
INSERT INTO t SELECT g % 100, g % 50 FROM generate_series(1, 1000) g;
CREATE STATISTICS t_s (mcv) ON a, b FROM t;
ANALYZE t;
SELECT pg_restore_extended_stats(
'schemaname', 'public', 'relname', 't',
'statistics_schemaname', 'public', 'statistics_name', 't_s',
'inherited', false,
'most_common_vals', (SELECT array_agg(ARRAY[g::text, (g*7)::text])
FROM generate_series(1, 10001) g),
'most_common_freqs', (SELECT array_agg((0.5/10001)::float8)
FROM generate_series(1, 10001) g),
'most_common_base_freqs', (SELECT array_agg((0.5/10001)::float8)
FROM generate_series(1, 10001) g));
-- returns t
EXPLAIN SELECT * FROM t WHERE a = 1 AND b = 7;
-- ERROR: invalid length (10001) item array in MCVList (XX000)
The statistics object is then unusable until cleared. With more than
65535 items, an assertion-enabled build crashes instead (the Assert in
mcv_get_match_bitmap()).
The cause is a write/read asymmetry: import_mcv()
(extended_stats_funcs.c) hands the input item count to
statext_mcv_import() unbounded, while statext_mcv_deserialize()
(mcv.c) rejects nitems > STATS_MCVLIST_MAX_ITEMS. This is the same
family as 6d6348f0329 (CVE-2026-6575) and 0b8fa5fd37b, both of which
note import_mcv() was not affected by their issue -- the item-count
bound is a separate, still-open gap.
The attached patch adds that bound to import_mcv(), rejecting an
oversized list with a WARNING before anything is stored. A regression
test is added to stats_import.sql; "make check" passes.
Thanks,
Ewan Young
| Attachment | Content-Type | Size |
|---|---|---|
| v1-0001-Reject-oversized-MCV-lists-in-extended-statistics.patch | application/octet-stream | 4.8 KB |
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Bharath Rupireddy | 2026-06-16 03:20:13 | Re: Disable startup progress timeout during standby WAL replay |
| Previous Message | Yingying Chen | 2026-06-16 03:09:58 | Re: Make frontend programs relink after libpgfeutils changes |