From bdd50eb3e6b31003cfb9bd3db8d729f1973d787c Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 8 Feb 2007 18:38:19 +0000 Subject: [PATCH] Fix an ancient logic error in plpgsql's exec_stmt_block: it thought it could get away with not (re)initializing a local variable if the variable is marked "isconst" and not "isnull". Unfortunately it makes this decision after having already freed the old value, meaning that something like for i in 1..10 loop declare c constant text := 'hi there'; leads to subsequent accesses to freed memory, and hence probably crashes. (In particular, this is why Asif Ali Rehman's bug leads to crash and not just an unexpectedly-NULL value for SQLERRM: SQLERRM is marked CONSTANT and so triggers this error.) The whole thing seems wrong on its face anyway: CONSTANT means that you can't change the variable inside the block, not that the initializer expression is guaranteed not to change value across successive block entries. Hence, remove the "optimization" instead of trying to fix it. --- src/pl/plpgsql/src/pl_exec.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index 57cdd065ff..c3f3932baf 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -799,29 +799,29 @@ exec_stmt_block(PLpgSQL_execstate * estate, PLpgSQL_stmt_block * block) { PLpgSQL_var *var = (PLpgSQL_var *) (estate->datums[n]); + /* free any old value, in case re-entering block */ if (var->freeval) { pfree((void *) (var->value)); var->freeval = false; } - if (!var->isconst || var->isnull) + /* Initially it contains a NULL */ + var->value = (Datum) 0; + var->isnull = true; + + if (var->default_val == NULL) + { + if (var->notnull) + ereport(ERROR, + (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), + errmsg("variable \"%s\" declared NOT NULL cannot default to NULL", + var->refname))); + } + else { - if (var->default_val == NULL) - { - var->value = (Datum) 0; - var->isnull = true; - if (var->notnull) - ereport(ERROR, - (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), - errmsg("variable \"%s\" declared NOT NULL cannot default to NULL", - var->refname))); - } - else - { - exec_assign_expr(estate, (PLpgSQL_datum *) var, - var->default_val); - } + exec_assign_expr(estate, (PLpgSQL_datum *) var, + var->default_val); } } break; -- 2.39.5