mirror of
https://github.com/postgres/postgres.git
synced 2025-07-31 22:04:40 +03:00
Fix search_path to a safe value during maintenance operations.
While executing maintenance operations (ANALYZE, CLUSTER, REFRESH MATERIALIZED VIEW, REINDEX, or VACUUM), set search_path to 'pg_catalog, pg_temp' to prevent inconsistent behavior. Functions that are used for functional indexes, in index expressions, or in materialized views and depend on a different search path must be declared with CREATE FUNCTION ... SET search_path='...'. This change was previously committed as05e1737351
, then reverted in commit2fcc7ee7af
because it was too late in the cycle. Preparation for the MAINTAIN privilege, which was previously reverted due to search_path manipulation hazards. Discussion: https://postgr.es/m/d4ccaf3658cb3c281ec88c851a09733cd9482f22.camel@j-davis.com Discussion: https://postgr.es/m/E1q7j7Y-000z1H-Hr%40gemulon.postgresql.org Discussion: https://postgr.es/m/e44327179e5c9015c8dda67351c04da552066017.camel%40j-davis.com Reviewed-by: Greg Stark, Nathan Bossart, Noah Misch
This commit is contained in:
@ -20,8 +20,11 @@ $node->safe_psql(
|
||||
'postgres', q(
|
||||
CREATE EXTENSION amcheck;
|
||||
|
||||
CREATE SCHEMA test_amcheck;
|
||||
SET search_path = test_amcheck;
|
||||
|
||||
CREATE FUNCTION ok_cmp (int4, int4)
|
||||
RETURNS int LANGUAGE sql AS
|
||||
RETURNS int LANGUAGE sql SET search_path = test_amcheck AS
|
||||
$$
|
||||
SELECT
|
||||
CASE WHEN $1 < $2 THEN -1
|
||||
@ -34,7 +37,7 @@ $node->safe_psql(
|
||||
--- Check 1: uniqueness violation.
|
||||
---
|
||||
CREATE FUNCTION ok_cmp1 (int4, int4)
|
||||
RETURNS int LANGUAGE sql AS
|
||||
RETURNS int LANGUAGE sql SET search_path = test_amcheck AS
|
||||
$$
|
||||
SELECT ok_cmp($1, $2);
|
||||
$$;
|
||||
@ -43,7 +46,7 @@ $node->safe_psql(
|
||||
--- Make values 768 and 769 look equal.
|
||||
---
|
||||
CREATE FUNCTION bad_cmp1 (int4, int4)
|
||||
RETURNS int LANGUAGE sql AS
|
||||
RETURNS int LANGUAGE sql SET search_path = test_amcheck AS
|
||||
$$
|
||||
SELECT
|
||||
CASE WHEN ($1 = 768 AND $2 = 769) OR
|
||||
@ -56,13 +59,13 @@ $node->safe_psql(
|
||||
--- Check 2: uniqueness violation without deduplication.
|
||||
---
|
||||
CREATE FUNCTION ok_cmp2 (int4, int4)
|
||||
RETURNS int LANGUAGE sql AS
|
||||
RETURNS int LANGUAGE sql SET search_path = test_amcheck AS
|
||||
$$
|
||||
SELECT ok_cmp($1, $2);
|
||||
$$;
|
||||
|
||||
CREATE FUNCTION bad_cmp2 (int4, int4)
|
||||
RETURNS int LANGUAGE sql AS
|
||||
RETURNS int LANGUAGE sql SET search_path = test_amcheck AS
|
||||
$$
|
||||
SELECT
|
||||
CASE WHEN $1 = $2 AND $1 = 400 THEN -1
|
||||
@ -74,13 +77,13 @@ $node->safe_psql(
|
||||
--- Check 3: uniqueness violation with deduplication.
|
||||
---
|
||||
CREATE FUNCTION ok_cmp3 (int4, int4)
|
||||
RETURNS int LANGUAGE sql AS
|
||||
RETURNS int LANGUAGE sql SET search_path = test_amcheck AS
|
||||
$$
|
||||
SELECT ok_cmp($1, $2);
|
||||
$$;
|
||||
|
||||
CREATE FUNCTION bad_cmp3 (int4, int4)
|
||||
RETURNS int LANGUAGE sql AS
|
||||
RETURNS int LANGUAGE sql SET search_path = test_amcheck AS
|
||||
$$
|
||||
SELECT bad_cmp2($1, $2);
|
||||
$$;
|
||||
@ -142,7 +145,7 @@ my ($result, $stdout, $stderr);
|
||||
# We have not yet broken the index, so we should get no corruption
|
||||
$result = $node->safe_psql(
|
||||
'postgres', q(
|
||||
SELECT bt_index_check('bttest_unique_idx1', true, true);
|
||||
SELECT bt_index_check('test_amcheck.bttest_unique_idx1', true, true);
|
||||
));
|
||||
is($result, '', 'run amcheck on non-broken bttest_unique_idx1');
|
||||
|
||||
@ -150,6 +153,7 @@ is($result, '', 'run amcheck on non-broken bttest_unique_idx1');
|
||||
# values to be equal.
|
||||
$node->safe_psql(
|
||||
'postgres', q(
|
||||
SET search_path = test_amcheck;
|
||||
UPDATE pg_catalog.pg_amproc SET
|
||||
amproc = 'bad_cmp1'::regproc
|
||||
WHERE amproc = 'ok_cmp1'::regproc;
|
||||
@ -157,7 +161,7 @@ $node->safe_psql(
|
||||
|
||||
($result, $stdout, $stderr) = $node->psql(
|
||||
'postgres', q(
|
||||
SELECT bt_index_check('bttest_unique_idx1', true, true);
|
||||
SELECT bt_index_check('test_amcheck.bttest_unique_idx1', true, true);
|
||||
));
|
||||
ok( $stderr =~ /index uniqueness is violated for index "bttest_unique_idx1"/,
|
||||
'detected uniqueness violation for index "bttest_unique_idx1"');
|
||||
@ -175,13 +179,14 @@ ok( $stderr =~ /index uniqueness is violated for index "bttest_unique_idx1"/,
|
||||
# but no uniqueness violation.
|
||||
($result, $stdout, $stderr) = $node->psql(
|
||||
'postgres', q(
|
||||
SELECT bt_index_check('bttest_unique_idx2', true, true);
|
||||
SELECT bt_index_check('test_amcheck.bttest_unique_idx2', true, true);
|
||||
));
|
||||
ok( $stderr =~ /item order invariant violated for index "bttest_unique_idx2"/,
|
||||
'detected item order invariant violation for index "bttest_unique_idx2"');
|
||||
|
||||
$node->safe_psql(
|
||||
'postgres', q(
|
||||
SET search_path = test_amcheck;
|
||||
UPDATE pg_catalog.pg_amproc SET
|
||||
amproc = 'ok_cmp2'::regproc
|
||||
WHERE amproc = 'bad_cmp2'::regproc;
|
||||
@ -189,7 +194,7 @@ $node->safe_psql(
|
||||
|
||||
($result, $stdout, $stderr) = $node->psql(
|
||||
'postgres', q(
|
||||
SELECT bt_index_check('bttest_unique_idx2', true, true);
|
||||
SELECT bt_index_check('test_amcheck.bttest_unique_idx2', true, true);
|
||||
));
|
||||
ok( $stderr =~ /index uniqueness is violated for index "bttest_unique_idx2"/,
|
||||
'detected uniqueness violation for index "bttest_unique_idx2"');
|
||||
@ -206,7 +211,7 @@ ok( $stderr =~ /index uniqueness is violated for index "bttest_unique_idx2"/,
|
||||
# but no uniqueness violation.
|
||||
($result, $stdout, $stderr) = $node->psql(
|
||||
'postgres', q(
|
||||
SELECT bt_index_check('bttest_unique_idx3', true, true);
|
||||
SELECT bt_index_check('test_amcheck.bttest_unique_idx3', true, true);
|
||||
));
|
||||
ok( $stderr =~ /item order invariant violated for index "bttest_unique_idx3"/,
|
||||
'detected item order invariant violation for index "bttest_unique_idx3"');
|
||||
@ -215,6 +220,7 @@ ok( $stderr =~ /item order invariant violated for index "bttest_unique_idx3"/,
|
||||
# with different visibility.
|
||||
$node->safe_psql(
|
||||
'postgres', q(
|
||||
SET search_path = test_amcheck;
|
||||
DELETE FROM bttest_unique3 WHERE 380 <= i AND i <= 420;
|
||||
INSERT INTO bttest_unique3 (SELECT * FROM generate_series(380, 420));
|
||||
INSERT INTO bttest_unique3 VALUES (400);
|
||||
@ -228,6 +234,7 @@ $node->safe_psql(
|
||||
|
||||
$node->safe_psql(
|
||||
'postgres', q(
|
||||
SET search_path = test_amcheck;
|
||||
UPDATE pg_catalog.pg_amproc SET
|
||||
amproc = 'ok_cmp3'::regproc
|
||||
WHERE amproc = 'bad_cmp3'::regproc;
|
||||
@ -235,7 +242,7 @@ $node->safe_psql(
|
||||
|
||||
($result, $stdout, $stderr) = $node->psql(
|
||||
'postgres', q(
|
||||
SELECT bt_index_check('bttest_unique_idx3', true, true);
|
||||
SELECT bt_index_check('test_amcheck.bttest_unique_idx3', true, true);
|
||||
));
|
||||
ok( $stderr =~ /index uniqueness is violated for index "bttest_unique_idx3"/,
|
||||
'detected uniqueness violation for index "bttest_unique_idx3"');
|
||||
|
@ -313,6 +313,8 @@ bt_index_check_internal(Oid indrelid, bool parentcheck, bool heapallindexed,
|
||||
SetUserIdAndSecContext(heaprel->rd_rel->relowner,
|
||||
save_sec_context | SECURITY_RESTRICTED_OPERATION);
|
||||
save_nestlevel = NewGUCNestLevel();
|
||||
SetConfigOption("search_path", GUC_SAFE_SEARCH_PATH, PGC_USERSET,
|
||||
PGC_S_SESSION);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
Reference in New Issue
Block a user