Reject non-ON-SELECT rules that are named "_RETURN".
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 17 Oct 2022 16:14:39 +0000 (12:14 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 17 Oct 2022 16:14:39 +0000 (12:14 -0400)
DefineQueryRewrite() has long required that ON SELECT rules be named
"_RETURN".  But we overlooked the converse case: we should forbid
non-ON-SELECT rules that are named "_RETURN".  In particular this
prevents using CREATE OR REPLACE RULE to overwrite a view's _RETURN
rule with some other kind of rule, thereby breaking the view.

Per bug #17646 from Kui Liu.  Back-patch to all supported branches.

Discussion: https://postgr.es/m/17646-70c93cfa40365776@postgresql.org

src/backend/rewrite/rewriteDefine.c

index 213eabfbb9f610ed69dbb5bc0b1a83197da708d2..09165b269b30a97e4473485357a4864a0364357f 100644 (file)
@@ -530,6 +530,18 @@ DefineQueryRewrite(const char *rulename,
                                                                RelationGetDescr(event_relation),
                                                                false, false);
                }
+
+               /*
+                * And finally, if it's not an ON SELECT rule then it must *not* be
+                * named _RETURN.  This prevents accidentally or maliciously replacing
+                * a view's ON SELECT rule with some other kind of rule.
+                */
+               if (strcmp(rulename, ViewSelectRuleName) == 0)
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+                                        errmsg("non-view rule for \"%s\" must not be named \"%s\"",
+                                                       RelationGetRelationName(event_relation),
+                                                       ViewSelectRuleName)));
        }
 
        /*