aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/functions.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2022-08-10 13:37:25 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2022-08-10 13:37:25 -0400
commit309857f9c1825d0591579579bdde2a8c8bd3e491 (patch)
tree2d187c6f8f5a4036f1a9b2bd6424c6556157e8ef /src/backend/executor/functions.c
parent92dc33a3a229f7d24b8c97b6a18b417d79cf4d97 (diff)
downloadpostgresql-309857f9c1825d0591579579bdde2a8c8bd3e491.tar.gz
postgresql-309857f9c1825d0591579579bdde2a8c8bd3e491.zip
Fix handling of R/W expanded datums that are passed to SQL functions.
fmgr_sql must make expanded-datum arguments read-only, because it's possible that the function body will pass the argument to more than one callee function. If one of those functions takes the datum's R/W property as license to scribble on it, then later callees will see an unexpected value, leading to wrong answers. From a performance standpoint, it'd be nice to skip this in the common case that the argument value is passed to only one callee. However, detecting that seems fairly hard, and certainly not something that I care to attempt in a back-patched bug fix. Per report from Adam Mackler. This has been broken since we invented expanded datums, so back-patch to all supported branches. Discussion: https://postgr.es/m/WScDU5qfoZ7PB2gXwNqwGGgDPmWzz08VdydcPFLhOwUKZcdWbblbo-0Lku-qhuEiZoXJ82jpiQU4hOjOcrevYEDeoAvz6nR0IU4IHhXnaCA=@mackler.email Discussion: https://postgr.es/m/187436.1660143060@sss.pgh.pa.us
Diffstat (limited to 'src/backend/executor/functions.c')
-rw-r--r--src/backend/executor/functions.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index 076226868f3..e134a82ff7e 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -939,6 +939,7 @@ postquel_sub_params(SQLFunctionCachePtr fcache,
if (nargs > 0)
{
ParamListInfo paramLI;
+ Oid *argtypes = fcache->pinfo->argtypes;
if (fcache->paramLI == NULL)
{
@@ -955,10 +956,24 @@ postquel_sub_params(SQLFunctionCachePtr fcache,
{
ParamExternData *prm = &paramLI->params[i];
- prm->value = fcinfo->args[i].value;
+ /*
+ * If an incoming parameter value is a R/W expanded datum, we
+ * force it to R/O. We'd be perfectly entitled to scribble on it,
+ * but the problem is that if the parameter is referenced more
+ * than once in the function, earlier references might mutate the
+ * value seen by later references, which won't do at all. We
+ * could do better if we could be sure of the number of Param
+ * nodes in the function's plans; but we might not have planned
+ * all the statements yet, nor do we have plan tree walker
+ * infrastructure. (Examining the parse trees is not good enough,
+ * because of possible function inlining during planning.)
+ */
prm->isnull = fcinfo->args[i].isnull;
+ prm->value = MakeExpandedObjectReadOnly(fcinfo->args[i].value,
+ prm->isnull,
+ get_typlen(argtypes[i]));
prm->pflags = 0;
- prm->ptype = fcache->pinfo->argtypes[i];
+ prm->ptype = argtypes[i];
}
}
else