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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy