aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDean Rasheed <dean.a.rasheed@gmail.com>2016-02-29 12:34:33 +0000
committerDean Rasheed <dean.a.rasheed@gmail.com>2016-02-29 12:34:33 +0000
commit9b69d5c1daeb62804eeaeab2f804191dbe0a943d (patch)
tree381525b6059d803b81f4820fe4e588837b9040d9 /src
parent80c925c7b4efcd80a8c648ca94ba1fabbd2863ae (diff)
downloadpostgresql-9b69d5c1daeb62804eeaeab2f804191dbe0a943d.tar.gz
postgresql-9b69d5c1daeb62804eeaeab2f804191dbe0a943d.zip
Fix incorrect varlevelsup in security_barrier_replace_vars().
When converting an RTE with securityQuals into a security barrier subquery RTE, ensure that the Vars in the new subquery's targetlist all have varlevelsup = 0 so that they correctly refer to the underlying base relation being wrapped. The original code was creating new Vars by copying them from existing Vars referencing the base relation found elsewhere in the query, but failed to account for the fact that such Vars could come from sublink subqueries, and hence have varlevelsup > 0. In practice it looks like this could only happen with nested security barrier views, where the outer view has a WHERE clause containing a correlated subquery, due to the order in which the Vars are processed. Bug: #13988 Reported-by: Adam Guthrie Backpatch-to: 9.4, where updatable SB views were introduced
Diffstat (limited to 'src')
-rw-r--r--src/backend/optimizer/prep/prepsecurity.c1
-rw-r--r--src/test/regress/expected/updatable_views.out39
-rw-r--r--src/test/regress/sql/updatable_views.sql34
3 files changed, 74 insertions, 0 deletions
diff --git a/src/backend/optimizer/prep/prepsecurity.c b/src/backend/optimizer/prep/prepsecurity.c
index c47b349fd40..0599ade8171 100644
--- a/src/backend/optimizer/prep/prepsecurity.c
+++ b/src/backend/optimizer/prep/prepsecurity.c
@@ -454,6 +454,7 @@ security_barrier_replace_vars_walker(Node *node,
/* New variable for subquery targetlist */
newvar = copyObject(var);
newvar->varno = newvar->varnoold = 1;
+ newvar->varlevelsup = 0;
attno = list_length(context->targetlist) + 1;
tle = makeTargetEntry((Expr *) newvar,
diff --git a/src/test/regress/expected/updatable_views.out b/src/test/regress/expected/updatable_views.out
index c9a5d30f1e7..f41386be1f9 100644
--- a/src/test/regress/expected/updatable_views.out
+++ b/src/test/regress/expected/updatable_views.out
@@ -2351,3 +2351,42 @@ DROP VIEW vx1;
DROP TABLE tx1;
DROP TABLE tx2;
DROP TABLE tx3;
+--
+-- Test handling of vars from correlated subqueries in quals from outer
+-- security barrier views, per bug #13988
+--
+CREATE TABLE t1 (a int, b text, c int);
+INSERT INTO t1 VALUES (1, 'one', 10);
+CREATE TABLE t2 (cc int);
+INSERT INTO t2 VALUES (10), (20);
+CREATE VIEW v1 WITH (security_barrier = true) AS
+ SELECT * FROM t1 WHERE (a > 0)
+ WITH CHECK OPTION;
+CREATE VIEW v2 WITH (security_barrier = true) AS
+ SELECT * FROM v1 WHERE EXISTS (SELECT 1 FROM t2 WHERE t2.cc = v1.c)
+ WITH CHECK OPTION;
+INSERT INTO v2 VALUES (2, 'two', 20); -- ok
+INSERT INTO v2 VALUES (-2, 'minus two', 20); -- not allowed
+ERROR: new row violates WITH CHECK OPTION for view "v1"
+DETAIL: Failing row contains (-2, minus two, 20).
+INSERT INTO v2 VALUES (3, 'three', 30); -- not allowed
+ERROR: new row violates WITH CHECK OPTION for view "v2"
+DETAIL: Failing row contains (3, three, 30).
+UPDATE v2 SET b = 'ONE' WHERE a = 1; -- ok
+UPDATE v2 SET a = -1 WHERE a = 1; -- not allowed
+ERROR: new row violates WITH CHECK OPTION for view "v1"
+DETAIL: Failing row contains (-1, ONE, 10).
+UPDATE v2 SET c = 30 WHERE a = 1; -- not allowed
+ERROR: new row violates WITH CHECK OPTION for view "v2"
+DETAIL: Failing row contains (1, ONE, 30).
+DELETE FROM v2 WHERE a = 2; -- ok
+SELECT * FROM v2;
+ a | b | c
+---+-----+----
+ 1 | ONE | 10
+(1 row)
+
+DROP VIEW v2;
+DROP VIEW v1;
+DROP TABLE t2;
+DROP TABLE t1;
diff --git a/src/test/regress/sql/updatable_views.sql b/src/test/regress/sql/updatable_views.sql
index 69d6b8e0ad0..78a3b0256a2 100644
--- a/src/test/regress/sql/updatable_views.sql
+++ b/src/test/regress/sql/updatable_views.sql
@@ -1055,3 +1055,37 @@ DROP VIEW vx1;
DROP TABLE tx1;
DROP TABLE tx2;
DROP TABLE tx3;
+
+--
+-- Test handling of vars from correlated subqueries in quals from outer
+-- security barrier views, per bug #13988
+--
+CREATE TABLE t1 (a int, b text, c int);
+INSERT INTO t1 VALUES (1, 'one', 10);
+
+CREATE TABLE t2 (cc int);
+INSERT INTO t2 VALUES (10), (20);
+
+CREATE VIEW v1 WITH (security_barrier = true) AS
+ SELECT * FROM t1 WHERE (a > 0)
+ WITH CHECK OPTION;
+
+CREATE VIEW v2 WITH (security_barrier = true) AS
+ SELECT * FROM v1 WHERE EXISTS (SELECT 1 FROM t2 WHERE t2.cc = v1.c)
+ WITH CHECK OPTION;
+
+INSERT INTO v2 VALUES (2, 'two', 20); -- ok
+INSERT INTO v2 VALUES (-2, 'minus two', 20); -- not allowed
+INSERT INTO v2 VALUES (3, 'three', 30); -- not allowed
+
+UPDATE v2 SET b = 'ONE' WHERE a = 1; -- ok
+UPDATE v2 SET a = -1 WHERE a = 1; -- not allowed
+UPDATE v2 SET c = 30 WHERE a = 1; -- not allowed
+
+DELETE FROM v2 WHERE a = 2; -- ok
+SELECT * FROM v2;
+
+DROP VIEW v2;
+DROP VIEW v1;
+DROP TABLE t2;
+DROP TABLE t1;