Обсуждение: 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

От
PG Bug reporting form
Дата:
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.


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