Thread: BUG #17972: Assert failed in pull_varattnos_walker() for view with subquery and security qual
BUG #17972: Assert failed in pull_varattnos_walker() for view with subquery and security qual
From
PG Bug reporting form
Date:
The following bug has been logged on the website: Bug reference: 17972 Logged by: Alexander Lakhin Email address: exclusion@gmail.com PostgreSQL version: 16beta1 Operating system: Ubuntu 22.04 Description: The following script: CREATE TABLE t1(a int); CREATE VIEW v1 WITH (security_barrier = true) AS SELECT a FROM t1; CREATE RULE v1_upd_rule AS ON UPDATE TO v1 DO INSTEAD UPDATE t1 SET a = NEW.a WHERE a = OLD.a; CREATE VIEW v2 WITH (security_barrier = true) AS SELECT a FROM v1 WHERE EXISTS (SELECT 1); UPDATE v2 SET a = 1; leads to a failed assertion with the stack trace: Core was generated by `postgres: law regression [local] UPDATE '. Program terminated with signal SIGABRT, Aborted. warning: Section `.reg-xstate/3314281' in core file too small. #0 __pthread_kill_implementation (no_tid=0, signo=6, threadid=140289111025600) at ./nptl/pthread_kill.c:44 44 ./nptl/pthread_kill.c: No such file or directory. (gdb) bt #0 __pthread_kill_implementation (no_tid=0, signo=6, threadid=140289111025600) at ./nptl/pthread_kill.c:44 #1 __pthread_kill_internal (signo=6, threadid=140289111025600) at ./nptl/pthread_kill.c:78 #2 __GI___pthread_kill (threadid=140289111025600, signo=signo@entry=6) at ./nptl/pthread_kill.c:89 #3 0x00007f9799eee476 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26 #4 0x00007f9799ed47f3 in __GI_abort () at ./stdlib/abort.c:79 #5 0x000055e8c9bc9a29 in ExceptionalCondition (conditionName=0x55e8ca47ec40 "!IsA(node, Query)", fileName=0x55e8ca47ebe0 "var.c", lineNumber=320) at assert.c:66 #6 0x000055e8c9045865 in pull_varattnos_walker (node=0x629000035da0, context=0x7ffe3dfdd800) at var.c:320 #7 0x000055e8c8c194b1 in expression_tree_walker_impl (node=0x62d00006f3d0, walker=0x55e8c90454b9 <pull_varattnos_walker>, context=0x7ffe3dfdd800) at nodeFuncs.c:2144 #8 0x000055e8c904587f in pull_varattnos_walker (node=0x62d00006f3d0, context=0x7ffe3dfdd800) at var.c:322 #9 0x000055e8c9045410 in pull_varattnos (node=0x62d00006f3d0, varno=2, varattnos=0x7ffe3dfdd8b0) at var.c:298 #10 0x000055e8c8da2da7 in remove_unused_subquery_outputs (subquery=0x62d00006fa58, rel=0x625000006070, extra_used_attrs=0x0) at allpaths.c:4105 #11 0x000055e8c8d98300 in set_subquery_pathlist (root=0x62500005b958, rel=0x625000006070, rti=2, rte=0x629000035c40) at allpaths.c:2626 #12 0x000055e8c8d8a008 in set_rel_size (root=0x62500005b958, rel=0x625000006070, rti=2, rte=0x629000035c40) at allpaths.c:424 #13 0x000055e8c8d897a1 in set_base_rel_sizes (root=0x62500005b958) at allpaths.c:325 #14 0x000055e8c8d8881b in make_one_rel (root=0x62500005b958, joinlist=0x62d00006fe40) at allpaths.c:186 #15 0x000055e8c8eb5073 in query_planner (root=0x62500005b958, qp_callback=0x55e8c8ed50b0 <standard_qp_callback>, qp_extra=0x7ffe3dfddef0) at planmain.c:278 #16 0x000055e8c8ec3f10 in grouping_planner (root=0x62500005b958, tuple_fraction=0) at planner.c:1493 #17 0x000055e8c8ec1574 in subquery_planner (glob=0x62d00006edf0, parse=0x629000035740, parent_root=0x0, hasRecursion=false, tuple_fraction=0) at planner.c:1062 #18 0x000055e8c8eb70a4 in standard_planner (parse=0x629000035740, query_string=0x625000005218 "UPDATE v2 SET a = 1;", cursorOptions=2048, boundParams=0x0) at planner.c:411 #19 0x000055e8c8eb5fd0 in planner (parse=0x629000035740, query_string=0x625000005218 "UPDATE v2 SET a = 1;", cursorOptions=2048, boundParams=0x0) at planner.c:281 #20 0x000055e8c945339e in pg_plan_query (querytree=0x629000035740, query_string=0x625000005218 "UPDATE v2 SET a = 1;", cursorOptions=2048, boundParams=0x0) at postgres.c:904 #21 0x000055e8c9453ca4 in pg_plan_queries (querytrees=0x62d00006e7c8, query_string=0x625000005218 "UPDATE v2 SET a = 1;", cursorOptions=2048, boundParams=0x0) at postgres.c:996 #22 0x000055e8c9454555 in exec_simple_query (query_string=0x625000005218 "UPDATE v2 SET a = 1;") at postgres.c:1193 #23 0x000055e8c9461e56 in PostgresMain (dbname=0x62900001b358 "regression", username=0x6250000020f8 "law") at postgres.c:4632 #24 0x000055e8c90d449d in BackendRun (port=0x614000000440) at postmaster.c:4461 #25 0x000055e8c90d2d23 in BackendStartup (port=0x614000000440) at postmaster.c:4189 #26 0x000055e8c90c941d in ServerLoop () at postmaster.c:1779 #27 0x000055e8c90c7a05 in PostmasterMain (argc=3, argv=0x603000000670) at postmaster.c:1463 #28 0x000055e8c8af536f in main (argc=3, argv=0x603000000670) at main.c:198 (gdb) frame 9 #9 0x000055e8c9045410 in pull_varattnos (node=0x62d00006f3d0, varno=2, varattnos=0x7ffe3dfdd8b0) at var.c:298 298 (void) pull_varattnos_walker(node, &context); (gdb) p *((SubLink *)node)->subselect $1 = {type = T_Query} (gdb) frame 12 #12 0x000055e8c8d8a008 in set_rel_size (root=0x62500005b958, rel=0x625000006070, rti=2, rte=0x629000035c40) at allpaths.c:424 424 set_subquery_pathlist(root, rel, rti, rte); (gdb) p *(Query *)((SubLink *)((RestrictInfo *)rel->baserestrictinfo->elements->ptr_value)->clause)->subselect $2 = {type = T_Query, commandType = CMD_SELECT, querySource = QSRC_ORIGINAL, ...} `git bisect` for this anomaly pointed at 215b43cdc. It looks like the failure caused by the following: 1) For a securiy view, the rewriteTargetView() call sets securityQuals; 2) subquery_planner() sets root->qual_security_level = 1 (Max(root->qual_security_level, list_length(rte->securityQuals))); 3) deconstruct_distribute() calls process_security_barrier_quals() -> distribute_qual_to_rels(), which performs "Add clause information to either the baserestrictinfo or joininfo list ..."; 4) Later, when set_rel_size() called, for the case rel->rtekind == RTE_SUBQUERY we get set_subquery_pathlist() called, which in turn calls remove_unused_subquery_outputs(), where foreach(lc, rel->baserestrictinfo) we have pull_varattnos() called with the clause->subselect having type T_QUERY, but a comment for pull_varattnos() says: * Currently, this does not support unplanned subqueries; that is not needed * for current uses. ... 5) And we really stumble upon the Assert in pull_varattnos_walker(). IIIUC, 215b43cdc produced this failure due to process_security_barrier_quals() added.
Re: BUG #17972: Assert failed in pull_varattnos_walker() for view with subquery and security qual
From
Tom Lane
Date:
PG Bug reporting form <noreply@postgresql.org> writes: > The following script: > CREATE TABLE t1(a int); > CREATE VIEW v1 WITH (security_barrier = true) AS SELECT a FROM t1; > CREATE RULE v1_upd_rule AS ON UPDATE TO v1 DO INSTEAD UPDATE t1 SET a = > NEW.a WHERE a = OLD.a; > CREATE VIEW v2 WITH (security_barrier = true) AS SELECT a FROM v1 WHERE > EXISTS (SELECT 1); > UPDATE v2 SET a = 1; > leads to a failed assertion with the stack trace: Thanks for the report! pull_varattnos is not at fault here. The problem is that we missed converting that SubLink to a SubPlan earlier, because hasSubLinks wasn't set in the parent Query, so we never called SS_process_sublinks. After some digging, I found the cause: rewriteRuleAction neglected to check for SubLink nodes in the securityQuals of range table entries. > `git bisect` for this anomaly pointed at 215b43cdc. I think this is just accidental, probably an artifact of the specific test case. The oversight in rewriteRuleAction is as old as the existence of RangeTblEntry.securityQuals, unless it was impossible to write a SubLink in security quals before, which I doubt. regards, tom lane