8000 plpgsql's exec_assign_value() freed the old value of a variable before · jandas/postgres@224501e · GitHub
[go: up one dir, main page]

Skip to content

Commit 224501e

Browse files
committed
plpgsql's exec_assign_value() freed the old value of a variable before
copying/converting the new value, which meant that it failed badly on "var := var" if var is of pass-by-reference type. Fix this and a similar hazard in exec_move_row(); not sure that the latter can manifest before 8.0, but patch it all the way back anyway. Per report from Dave Chapeskie.
1 parent 2b91c8c commit 224501e

File tree

1 file changed

+30
-23
lines changed

1 file changed

+30
-23
lines changed

src/pl/plpgsql/src/pl_exec.c

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* procedural language
44
*
55
* IDENTIFICATION
6-
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.52.2.1 2002/03/25 07:41:21 tgl Exp $
6+
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.52.2.2 2005/06/20 20:45:12 tgl Exp $
77
*
88
* This software is copyrighted by Jan Wieck - Hamburg.
99
*
@@ -2665,12 +2665,6 @@ exec_assign_value(PLpgSQL_execstate * estate,
26652665
*/
26662666
var = (PLpgSQL_var *) target;
26672667

2668-
if (var->freeval)
2669-
{
2670-
pfree((void *) (var->value));
2671-
var->freeval = false;
2672-
}
2673-
26742668
newvalue = exec_cast_value(value, valtype, var->datatype->typoid,
26752669
&(var->datatype->typinput),
26762670
var->datatype->typelem,
@@ -2690,23 +2684,28 @@ exec_assign_value(PLpgSQL_execstate * estate,
26902684
if (!var->datatype->typbyval && !*isNull)
26912685
{
26922686
if (newvalue == value)
2693-
{
2694-
int len;
2687+
newvalue = datumCopy(newvalue,
2688+
false,
2689+
var->datatype->typlen);
2690+
}
26952691

2696-
if (var->datatype->typlen < 0)
2697-
len = VARSIZE(newvalue);
2698-
else
2699-
len = var->datatype->typlen;
2700-
var->value = (Datum) palloc(len);
2701-
memcpy((void *) (var->value), (void *) newvalue, len);
2702-
}
2703-
else
2704-
var->value = newvalue;
2705-
var->freeval = true;
2692+
/*
2693+
* Now free the old value. (We can't do this any earlier
2694+
* because of the possibility that we are assigning the
2695+
* var's old value to it, eg "foo := foo". We could optimize
2696+
* out the assignment altogether in such cases, but it's too
2697+
* infrequent to be worth testing for.)
2698+
*/
2699+
if (var->freeval)
2700+
{
2701+
pfree(DatumGetPointer(var->value));
2702+
var->freeval = false;
27062703
}
2707-
else
2708-
var->value = newvalue;
2704+
2705+
var->value = newvalue;
27092706
var->isnull = *isNull;
2707+
if (!var->datatype->typbyval && !*isNull)
2708+
var->freeval = true;
27102709
break;
27112710

27122711
case PLPGSQL_DTYPE_RECFIELD:
@@ -3145,6 +3144,14 @@ exec_move_row(PLpgSQL_execstate * estate,
31453144
*/
31463145
if (rec != NULL)
31473146
{
3147+
/*
3148+
* copy input first, just in case it is pointing at variable's value
3149+
*/
3150+
if (HeapTupleIsValid(tup))
3151+
tup = heap_copytuple(tup);
3152+
if (tupdesc)
3153+
tupdesc = CreateTupleDescCopy(tupdesc);
3154+
31483155
if (rec->freetup)
31493156
{
31503157
heap_freetuple(rec->tup);
@@ -3158,8 +3165,8 @@ exec_move_row(PLpgSQL_execstate * estate,
31583165

31593166
if (HeapTupleIsValid(tup))
31603167
{
3161-
rec->tup = heap_copytuple(tup);
3162-
rec->tupdesc = CreateTupleDescCopy(tupdesc);
3168+
rec->tup = tup;
3169+
rec->tupdesc = tupdesc;
31633170
rec->freetup = true;
31643171
rec->freetupdesc = true;
31653172
}

0 commit comments

Comments
 (0)
0