Read/write expanded objects versus domains and CASE
Tom Lane <tgl@sss.pgh.pa.us>
From: Tom Lane <tgl@sss.pgh.pa.us>
To: pgsql-hackers@postgreSQL.org
Date: 2016-12-22T18:33:39Z
Lists: pgsql-hackers
Attachments
- fix-rw-objects-in-domains-and-CASE.patch (text/x-diff) patch
I looked into the problem reported in bug #14472, https://www.postgresql.org/message-id/20161221214744.25622.71454@wrigleys.postgresql.org Although the submitter thought it was related to bug #14414, it isn't particularly. The failure scenario is that the input value to a CoerceToDomain execution node is a read-write expanded datum. We were blindly passing that to any CHECK constraint expressions for the domain type, which leaves called functions at liberty to modify or even delete the expanded object. Correct behavior is to pass a read-only pointer to the CHECK expressions and then return the original read-write pointer as the expression result. I nosed around for other occurrences of the same problem and soon realized that CASE with an "arg" expression has a similar issue, since the "arg" value may get passed to multiple test expressions. It'd be substantially harder to make a test case for that in the current state of the code --- to get a failure, you'd need a plpgsql function to be the equality operator for some data type --- but it's surely not impossible. Also, domain_check() could in principle be called with a r/w datum, so it should also protect against this. The fix for this is nominally simple, to call MakeExpandedObjectReadOnly at the appropriate places; but that requires having the data type's typlen at hand, which we don't in these places. In the domain cases, the typlen is cheaply accessible through the domain's typcache entry, which we could get at as long as we don't mind using DomainConstraintRef.tcache, which had been documented as private to typcache.c. I don't see any particularly strong reason not to allow callers to use it, though. In the CASE case, there seems no help for it except to expend a get_typlen() syscache lookup during executor setup. It's kind of annoying to do that to support a corner case that may very well never occur in the field, but I don't see another alternative. So I'm proposing the attached patch (sans test cases as yet). Any objections? regards, tom lane
Commits
-
Fix handling of expanded objects in CoerceToDomain and CASE execution.
- c472f2a3353d 9.5.6 landed
- 77cd0dc7e05a 9.6.2 landed
- cd1b215692d2 10.0 landed