diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/executor/execQual.c | 25 | ||||
-rw-r--r-- | src/backend/utils/adt/domains.c | 10 |
2 files changed, 28 insertions, 7 deletions
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c index a6c9b6a66b4..169134d45c6 100644 --- a/src/backend/executor/execQual.c +++ b/src/backend/executor/execQual.c @@ -2960,12 +2960,18 @@ ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext, if (caseExpr->arg) { + Datum arg_value; bool arg_isNull; - econtext->caseValue_datum = ExecEvalExpr(caseExpr->arg, - econtext, - &arg_isNull, - NULL); + arg_value = ExecEvalExpr(caseExpr->arg, + econtext, + &arg_isNull, + NULL); + /* Since caseValue_datum may be read multiple times, force to R/O */ + econtext->caseValue_datum = + MakeExpandedObjectReadOnly(arg_value, + arg_isNull, + caseExpr->argtyplen); econtext->caseValue_isNull = arg_isNull; } @@ -4026,11 +4032,18 @@ ExecEvalCoerceToDomain(CoerceToDomainState *cstate, ExprContext *econtext, * nodes. We must save and restore prior setting of * econtext's domainValue fields, in case this node is * itself within a check expression for another domain. + * + * Also, if we are working with a read-write expanded + * datum, be sure that what we pass to CHECK expressions + * is a read-only pointer; else called functions might + * modify or even delete the expanded object. */ save_datum = econtext->domainValue_datum; save_isNull = econtext->domainValue_isNull; - econtext->domainValue_datum = result; + econtext->domainValue_datum = + MakeExpandedObjectReadOnly(result, *isNull, + cstate->constraint_ref->tcache->typlen); econtext->domainValue_isNull = *isNull; conResult = ExecEvalExpr(con->check_expr, @@ -4858,6 +4871,8 @@ ExecInitExpr(Expr *node, PlanState *parent) } cstate->args = outlist; cstate->defresult = ExecInitExpr(caseexpr->defresult, parent); + if (caseexpr->arg) + cstate->argtyplen = get_typlen(exprType((Node *) caseexpr->arg)); state = (ExprState *) cstate; } break; diff --git a/src/backend/utils/adt/domains.c b/src/backend/utils/adt/domains.c index ac8c25266e0..9cf98a8f6b4 100644 --- a/src/backend/utils/adt/domains.c +++ b/src/backend/utils/adt/domains.c @@ -35,6 +35,7 @@ #include "executor/executor.h" #include "lib/stringinfo.h" #include "utils/builtins.h" +#include "utils/expandeddatum.h" #include "utils/lsyscache.h" #include "utils/syscache.h" #include "utils/typcache.h" @@ -157,9 +158,14 @@ domain_check_input(Datum value, bool isnull, DomainIOData *my_extra) * Set up value to be returned by CoerceToDomainValue * nodes. Unlike ExecEvalCoerceToDomain, this econtext * couldn't be shared with anything else, so no need to - * save and restore fields. + * save and restore fields. But we do need to protect the + * passed-in value against being changed by called + * functions. (It couldn't be a R/W expanded object for + * most uses, but that seems possible for domain_check().) */ - econtext->domainValue_datum = value; + econtext->domainValue_datum = + MakeExpandedObjectReadOnly(value, isnull, + my_extra->constraint_ref.tcache->typlen); econtext->domainValue_isNull = isnull; conResult = ExecEvalExprSwitchContext(con->check_expr, |