/* * fix-CVE-2024-4317.sql * * Copyright (c) 2024, PostgreSQL Global Development Group * * src/backend/catalog/fix-CVE-2024-4317.sql * * This file should be run in every database in the cluster to address * CVE-2024-4317. */ SET search_path = pg_catalog; CREATE OR REPLACE VIEW pg_stats_ext WITH (security_barrier) AS SELECT cn.nspname AS schemaname, c.relname AS tablename, sn.nspname AS statistics_schemaname, s.stxname AS statistics_name, pg_get_userbyid(s.stxowner) AS statistics_owner, ( SELECT array_agg(a.attname ORDER BY a.attnum) FROM unnest(s.stxkeys) k JOIN pg_attribute a ON (a.attrelid = s.stxrelid AND a.attnum = k) ) AS attnames, pg_get_statisticsobjdef_expressions(s.oid) as exprs, s.stxkind AS kinds, sd.stxdinherit AS inherited, sd.stxdndistinct AS n_distinct, sd.stxddependencies AS dependencies, m.most_common_vals, m.most_common_val_nulls, m.most_common_freqs, m.most_common_base_freqs FROM pg_statistic_ext s JOIN pg_class c ON (c.oid = s.stxrelid) JOIN pg_statistic_ext_data sd ON (s.oid = sd.stxoid) LEFT JOIN pg_namespace cn ON (cn.oid = c.relnamespace) LEFT JOIN pg_namespace sn ON (sn.oid = s.stxnamespace) LEFT JOIN LATERAL ( SELECT array_agg(values) AS most_common_vals, array_agg(nulls) AS most_common_val_nulls, array_agg(frequency) AS most_common_freqs, array_agg(base_frequency) AS most_common_base_freqs FROM pg_mcv_list_items(sd.stxdmcv) ) m ON sd.stxdmcv IS NOT NULL WHERE pg_has_role(c.relowner, 'USAGE') AND (c.relrowsecurity = false OR NOT row_security_active(c.oid)); CREATE OR REPLACE VIEW pg_stats_ext_exprs WITH (security_barrier) AS SELECT cn.nspname AS schemaname, c.relname AS tablename, sn.nspname AS statistics_schemaname, s.stxname AS statistics_name, pg_get_userbyid(s.stxowner) AS statistics_owner, stat.expr, sd.stxdinherit AS inherited, (stat.a).stanullfrac AS null_frac, (stat.a).stawidth AS avg_width, (stat.a).stadistinct AS n_distinct, (CASE WHEN (stat.a).stakind1 = 1 THEN (stat.a).stavalues1 WHEN (stat.a).stakind2 = 1 THEN (stat.a).stavalues2 WHEN (stat.a).stakind3 = 1 THEN (stat.a).stavalues3 WHEN (stat.a).stakind4 = 1 THEN (stat.a).stavalues4 WHEN (stat.a).stakind5 = 1 THEN (stat.a).stavalues5 END) AS most_common_vals, (CASE WHEN (stat.a).stakind1 = 1 THEN (stat.a).stanumbers1 WHEN (stat.a).stakind2 = 1 THEN (stat.a).stanumbers2 WHEN (stat.a).stakind3 = 1 THEN (stat.a).stanumbers3 WHEN (stat.a).stakind4 = 1 THEN (stat.a).stanumbers4 WHEN (stat.a).stakind5 = 1 THEN (stat.a).stanumbers5 END) AS most_common_freqs, (CASE WHEN (stat.a).stakind1 = 2 THEN (stat.a).stavalues1 WHEN (stat.a).stakind2 = 2 THEN (stat.a).stavalues2 WHEN (stat.a).stakind3 = 2 THEN (stat.a).stavalues3 WHEN (stat.a).stakind4 = 2 THEN (stat.a).stavalues4 WHEN (stat.a).stakind5 = 2 THEN (stat.a).stavalues5 END) AS histogram_bounds, (CASE WHEN (stat.a).stakind1 = 3 THEN (stat.a).stanumbers1[1] WHEN (stat.a).stakind2 = 3 THEN (stat.a).stanumbers2[1] WHEN (stat.a).stakind3 = 3 THEN (stat.a).stanumbers3[1] WHEN (stat.a).stakind4 = 3 THEN (stat.a).stanumbers4[1] WHEN (stat.a).stakind5 = 3 THEN (stat.a).stanumbers5[1] END) correlation, (CASE WHEN (stat.a).stakind1 = 4 THEN (stat.a).stavalues1 WHEN (stat.a).stakind2 = 4 THEN (stat.a).stavalues2 WHEN (stat.a).stakind3 = 4 THEN (stat.a).stavalues3 WHEN (stat.a).stakind4 = 4 THEN (stat.a).stavalues4 WHEN (stat.a).stakind5 = 4 THEN (stat.a).stavalues5 END) AS most_common_elems, (CASE WHEN (stat.a).stakind1 = 4 THEN (stat.a).stanumbers1 WHEN (stat.a).stakind2 = 4 THEN (stat.a).stanumbers2 WHEN (stat.a).stakind3 = 4 THEN (stat.a).stanumbers3 WHEN (stat.a).stakind4 = 4 THEN (stat.a).stanumbers4 WHEN (stat.a).stakind5 = 4 THEN (stat.a).stanumbers5 END) AS most_common_elem_freqs, (CASE WHEN (stat.a).stakind1 = 5 THEN (stat.a).stanumbers1 WHEN (stat.a).stakind2 = 5 THEN (stat.a).stanumbers2 WHEN (stat.a).stakind3 = 5 THEN (stat.a).stanumbers3 WHEN (stat.a).stakind4 = 5 THEN (stat.a).stanumbers4 WHEN (stat.a).stakind5 = 5 THEN (stat.a).stanumbers5 END) AS elem_count_histogram FROM pg_statistic_ext s JOIN pg_class c ON (c.oid = s.stxrelid) LEFT JOIN pg_statistic_ext_data sd ON (s.oid = sd.stxoid) LEFT JOIN pg_namespace cn ON (cn.oid = c.relnamespace) LEFT JOIN pg_namespace sn ON (sn.oid = s.stxnamespace) JOIN LATERAL ( SELECT unnest(pg_get_statisticsobjdef_expressions(s.oid)) AS expr, unnest(sd.stxdexpr)::pg_statistic AS a ) stat ON (stat.expr IS NOT NULL) WHERE pg_has_role(c.relowner, 'USAGE') AND (c.relrowsecurity = false OR NOT row_security_active(c.oid));