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 d577d8d368f2435cc953bb5238fe791ce0bbb657..ac68913d8b7085fb4b4dc22c199a8366b6d14915 100644 (file)
@@ -532,6 +532,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)));
    }
 
    /*