Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 1f653ec

Browse files
committed
I have attached two patches as per:
1) pltcl: Add SPI_freetuptable() calls to avoid memory leaks (Me + Neil Conway) Change sprintf()s to snprintf()s (Neil Conway) Remove header files included elsewhere (Neil Conway) 2)plpython: Add SPI_freetuptable() calls to avoid memory leaks Cosemtic change to remove a compiler warning Notes: I have tested pltcl.c for a) the original leak problem reported for the repeated call of spi_exec in a TCL fragment and b) the subsequent report resulting from the use of spi_exec -array in a TCL fragment. The plpython.c patch is exactly the same as that applied to make revision 1.23, the plpython_schema.sql and feature.expected sections of the patch are also the same as last submited, applied and subsequently reversed out. It remains untested by me (other than via make check). However, this should be safe provided PyString_FromString() _copies_ the given string to make a PyObject. Nigel J. Andrews
1 parent daaf999 commit 1f653ec

File tree

4 files changed

+60
-27
lines changed

4 files changed

+60
-27
lines changed

src/pl/plpython/feature.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ SELECT global_test_two();
2929
(1 row)
3030

3131
SELECT import_fail();
32-
WARNING: ('import socket failed -- untrusted dynamic module: _socket',)
32+
NOTICE: ('import socket failed -- untrusted dynamic module: _socket',)
3333
import_fail
3434
--------------------
3535
failed as expected

src/pl/plpython/plpython.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
* MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
3030
*
3131
* IDENTIFICATION
32-
* $Header: /cvsroot/pgsql/src/pl/plpython/plpython.c,v 1.24 2002/09/26 05:39:03 momjian Exp $
32+
* $Header: /cvsroot/pgsql/src/pl/plpython/plpython.c,v 1.25 2002/10/14 04:20:52 momjian Exp $
3333
*
3434
*********************************************************************
3535
*/
@@ -408,7 +408,9 @@ plpython_call_handler(PG_FUNCTION_ARGS)
408408
else
409409
PLy_restart_in_progress += 1;
410410
if (proc)
411+
{
411412
Py_DECREF(proc->me);
413+
}
412414
RERAISE_EXC();
413415
}
414416

@@ -1841,7 +1843,14 @@ PLy_plan_dealloc(PyObject * arg)
18411843
*
18421844
* FIXME -- leaks saved plan on object destruction. can this be
18431845
* avoided?
1846+
* I think so. A function prepares and then execp's a statement.
1847+
* When we come to deallocate the 'statement' object we obviously
1848+
* no long need the plan. Even if we did, without the object
1849+
* we're never going to be able to use it again.
1850+
* In the against arguments: SPI_saveplan has stuck this under
1851+
* the top context so there must be a reason for doing that.
18441852
*/
1853+
pfree(ob->plan);
18451854
}
18461855
if (ob->types)
18471856
PLy_free(ob->types);
@@ -2374,6 +2383,8 @@ PLy_spi_execute_fetch_result(SPITupleTable *tuptable, int rows, int status)
23742383
PyList_SetItem(result->rows, i, row);
23752384
}
23762385
PLy_typeinfo_dealloc(&args);
2386+
2387+
SPI_freetuptable(tuptable);
23772388
}
23782389
RESTORE_EXC();
23792390
}

src/pl/plpython/plpython_schema.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ CREATE TABLE taxonomy (
2020

2121
CREATE TABLE entry (
2222
accession text not null primary key,
23-
eid serial,
23+
eid serial unique,
2424
txid int2 not null references taxonomy(id)
2525
) ;
2626

src/pl/tcl/pltcl.c

Lines changed: 46 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,16 @@
3131
* ENHANCEMENTS, OR MODIFICATIONS.
3232
*
3333
* IDENTIFICATION
34-
* $Header: /cvsroot/pgsql/src/pl/tcl/pltcl.c,v 1.64 2002/09/26 05:39:03 momjian Exp $
34+
* $Header: /cvsroot/pgsql/src/pl/tcl/pltcl.c,v 1.65 2002/10/14 04:20:52 momjian Exp $
3535
*
3636
**********************************************************************/
3737

3838
#include "postgres.h"
3939

4040
#include <tcl.h>
4141

42-
#include <stdio.h>
43-
#include <stdlib.h>
44-
#include <stdarg.h>
4542
#include <unistd.h>
4643
#include <fcntl.h>
47-
#include <string.h>
4844
#include <setjmp.h>
4945

5046
#include "access/heapam.h"
@@ -308,6 +304,7 @@ pltcl_init_load_unknown(Tcl_Interp *interp)
308304
************************************************************/
309305
spi_rc = SPI_exec("select 1 from pg_class "
310306
"where relname = 'pltcl_modules'", 1);
307+
SPI_freetuptable(SPI_tuptable);
311308
if (spi_rc != SPI_OK_SELECT)
312309
elog(ERROR, "pltcl_init_load_unknown(): select from pg_class failed");
313310
if (SPI_processed == 0)
@@ -334,6 +331,7 @@ pltcl_init_load_unknown(Tcl_Interp *interp)
334331
if (SPI_processed == 0)
335332
{
336333
Tcl_DStringFree(&unknown_src);
334+
SPI_freetuptable(SPI_tuptable);
337335
elog(WARNING, "pltcl: Module unknown not found in pltcl_modules");
338336
return;
339337
}
@@ -359,6 +357,7 @@ pltcl_init_load_unknown(Tcl_Interp *interp)
359357
}
360358
tcl_rc = Tcl_GlobalEval(interp, Tcl_DStringValue(&unknown_src));
361359
Tcl_DStringFree(&unknown_src);
360+
SPI_freetuptable(SPI_tuptable);
362361
}
363362

364363

@@ -955,9 +954,11 @@ compile_pltcl_function(Oid fn_oid, bool is_trigger)
955954
* Build our internal proc name from the functions Oid
956955
************************************************************/
957956
if (!is_trigger)
958-
sprintf(internal_proname, "__PLTcl_proc_%u", fn_oid);
957+
snprintf(internal_proname, sizeof(internal_proname),
958+
"__PLTcl_proc_%u", fn_oid);
959959
else
960-
sprintf(internal_proname, "__PLTcl_proc_%u_trigger", fn_oid);
960+
snprintf(internal_proname, sizeof(internal_proname),
961+
"__PLTcl_proc_%u_trigger", fn_oid);
961962

962963
/************************************************************
963964
* Lookup the internal proc name in the hashtable
@@ -1127,7 +1128,7 @@ compile_pltcl_function(Oid fn_oid, bool is_trigger)
11271128
prodesc->arg_is_rel[i] = 1;
11281129
if (i > 0)
11291130
strcat(proc_internal_args, " ");
1130-
sprintf(buf, "__PLTcl_Tup_%d", i + 1);
1131+
snprintf(buf, sizeof(buf), "__PLTcl_Tup_%d", i + 1);
11311132
strcat(proc_internal_args, buf);
11321133
ReleaseSysCache(typeTup);
11331134
continue;
@@ -1140,7 +1141,7 @@ compile_pltcl_function(Oid fn_oid, bool is_trigger)
11401141

11411142
if (i > 0)
11421143
strcat(proc_internal_args, " ");
1143-
sprintf(buf, "%d", i + 1);
1144+
snprintf(buf, sizeof(buf), "%d", i + 1);
11441145
strcat(proc_internal_args, buf);
11451146

11461147
ReleaseSysCache(typeTup);
@@ -1177,7 +1178,8 @@ compile_pltcl_function(Oid fn_oid, bool is_trigger)
11771178
{
11781179
if (!prodesc->arg_is_rel[i])
11791180
continue;
1180-
sprintf(buf, "array set %d $__PLTcl_Tup_%d\n", i + 1, i + 1);
1181+
snprintf(buf, sizeof(buf), "array set %d $__PLTcl_Tup_%d\n",
1182+
i + 1, i + 1);
11811183
Tcl_DStringAppend(&proc_internal_body, buf, -1);
11821184
}
11831185
}
@@ -1475,6 +1477,7 @@ pltcl_SPI_exec(ClientData cdata, Tcl_Interp *interp,
14751477
int ntuples;
14761478
HeapTuple *volatile tuples;
14771479
volatile TupleDesc tupdesc = NULL;
1480+
SPITupleTable *tuptable;
14781481
sigjmp_buf save_restart;
14791482

14801483
char *usage = "syntax error - 'SPI_exec "
@@ -1557,14 +1560,16 @@ pltcl_SPI_exec(ClientData cdata, Tcl_Interp *interp,
15571560
{
15581561
case SPI_OK_UTILITY:
15591562
Tcl_SetResult(interp, "0", TCL_VOLATILE);
1563+
SPI_freetuptable(SPI_tuptable);
15601564
return TCL_OK;
15611565

15621566
case SPI_OK_SELINTO:
15631567
case SPI_OK_INSERT:
15641568
case SPI_OK_DELETE:
15651569
case SPI_OK_UPDATE:
1566-
sprintf(buf, "%d", SPI_processed);
1570+
snprintf(buf, sizeof(buf), "%d", SPI_processed);
15671571
Tcl_SetResult(interp, buf, TCL_VOLATILE);
1572+
SPI_freetuptable(SPI_tuptable);
15681573
return TCL_OK;
15691574

15701575
case SPI_OK_SELECT:
@@ -1607,7 +1612,7 @@ pltcl_SPI_exec(ClientData cdata, Tcl_Interp *interp,
16071612
return TCL_ERROR;
16081613

16091614
default:
1610-
sprintf(buf, "%d", spi_rc);
1615+
snprintf(buf, sizeof(buf), "%d", spi_rc);
16111616
Tcl_AppendResult(interp, "pltcl: SPI_exec() failed - ",
16121617
"unknown RC ", buf, NULL);
16131618
return TCL_ERROR;
@@ -1645,12 +1650,15 @@ pltcl_SPI_exec(ClientData cdata, Tcl_Interp *interp,
16451650
{
16461651
if (ntuples > 0)
16471652
pltcl_set_tuple_values(interp, arrayname, 0, tuples[0], tupdesc);
1648-
sprintf(buf, "%d", ntuples);
1653+
snprintf(buf, sizeof(buf), "%d", ntuples);
16491654
Tcl_SetResult(interp, buf, TCL_VOLATILE);
1655+
SPI_freetuptable(SPI_tuptable);
16501656
memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
16511657
return TCL_OK;
16521658
}
16531659

1660+
tuptable = SPI_tuptable;
1661+
16541662
/************************************************************
16551663
* There is a loop body - process all tuples and evaluate
16561664
* the body on each
@@ -1668,20 +1676,24 @@ pltcl_SPI_exec(ClientData cdata, Tcl_Interp *interp,
16681676
continue;
16691677
if (loop_rc == TCL_RETURN)
16701678
{
1679+
SPI_freetuptable(tuptable);
16711680
memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
16721681
return TCL_RETURN;
16731682
}
16741683
if (loop_rc == TCL_BREAK)
16751684
break;
1685+
SPI_freetuptable(tuptable);
16761686
memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
16771687
return TCL_ERROR;
16781688
}
16791689

1690+
SPI_freetuptable(tuptable);
1691+
16801692
/************************************************************
16811693
* Finally return the number of tuples
16821694
************************************************************/
16831695
memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
1684-
sprintf(buf, "%d", ntuples);
1696+
snprintf(buf, sizeof(buf), "%d", ntuples);
16851697
Tcl_SetResult(interp, buf, TCL_VOLATILE);
16861698
return TCL_OK;
16871699
}
@@ -1690,7 +1702,7 @@ pltcl_SPI_exec(ClientData cdata, Tcl_Interp *interp,
16901702
/**********************************************************************
16911703
* pltcl_SPI_prepare() - Builtin support for prepared plans
16921704
* The Tcl command SPI_prepare
1693-
* allways saves the plan using
1705+
* always saves the plan using
16941706
* SPI_saveplan and returns a key for
16951707
* access. There is no chance to prepare
16961708
* and not save the plan currently.
@@ -1736,7 +1748,7 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
17361748
* Allocate the new querydesc structure
17371749
************************************************************/
17381750
qdesc = (pltcl_query_desc *) malloc(sizeof(pltcl_query_desc));
1739-
sprintf(qdesc->qname, "%lx", (long) qdesc);
1751+
snprintf(qdesc->qname, sizeof(qdesc->qname), "%lx", (long) qdesc);
17401752
qdesc->nargs = nargs;
17411753
qdesc->argtypes = (Oid *) malloc(nargs * sizeof(Oid));
17421754
qdesc->arginfuncs = (FmgrInfo *) malloc(nargs * sizeof(FmgrInfo));
@@ -1815,7 +1827,7 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
18151827
break;
18161828

18171829
default:
1818-
sprintf(buf, "unknown RC %d", SPI_result);
1830+
snprintf(buf, sizeof(buf), "unknown RC %d", SPI_result);
18191831
reason = buf;
18201832
break;
18211833

@@ -1846,7 +1858,7 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
18461858
break;
18471859

18481860
default:
1849-
sprintf(buf, "unknown RC %d", SPI_result);
1861+
snprintf(buf, sizeof(buf), "unknown RC %d", SPI_result);
18501862
reason = buf;
18511863
break;
18521864

@@ -1897,6 +1909,7 @@ pltcl_SPI_execp(ClientData cdata, Tcl_Interp *interp,
18971909
int ntuples;
18981910
HeapTuple *volatile tuples = NULL;
18991911
volatile TupleDesc tupdesc = NULL;
1912+
SPITupleTable *tuptable;
19001913
sigjmp_buf save_restart;
19011914
Tcl_HashTable *query_hash;
19021915

@@ -2116,14 +2129,16 @@ pltcl_SPI_execp(ClientData cdata, Tcl_Interp *interp,
21162129
{
21172130
case SPI_OK_UTILITY:
21182131
Tcl_SetResult(interp, "0", TCL_VOLATILE);
2132+
SPI_freetuptable(SPI_tuptable);
21192133
return TCL_OK;
21202134

21212135
case SPI_OK_SELINTO:
21222136
case SPI_OK_INSERT:
21232137
case SPI_OK_DELETE:
21242138
case SPI_OK_UPDATE:
2125-
sprintf(buf, "%d", SPI_processed);
2139+
snprintf(buf, sizeof(buf), "%d", SPI_processed);
21262140
Tcl_SetResult(interp, buf, TCL_VOLATILE);
2141+
SPI_freetuptable(SPI_tuptable);
21272142
return TCL_OK;
21282143

21292144
case SPI_OK_SELECT:
@@ -2166,7 +2181,7 @@ pltcl_SPI_execp(ClientData cdata, Tcl_Interp *interp,
21662181
return TCL_ERROR;
21672182

21682183
default:
2169-
sprintf(buf, "%d", spi_rc);
2184+
snprintf(buf, sizeof(buf), "%d", spi_rc);
21702185
Tcl_AppendResult(interp, "pltcl: SPI_exec() failed - ",
21712186
"unknown RC ", buf, NULL);
21722187
return TCL_ERROR;
@@ -2208,11 +2223,14 @@ pltcl_SPI_execp(ClientData cdata, Tcl_Interp *interp,
22082223
if (ntuples > 0)
22092224
pltcl_set_tuple_values(interp, arrayname, 0, tuples[0], tupdesc);
22102225
memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
2211-
sprintf(buf, "%d", ntuples);
2226+
snprintf(buf, sizeof(buf), "%d", ntuples);
22122227
Tcl_SetResult(interp, buf, TCL_VOLATILE);
2228+
SPI_freetuptable(SPI_tuptable);
22132229
return TCL_OK;
22142230
}
22152231

2232+
tuptable = SPI_tuptable;
2233+
22162234
/************************************************************
22172235
* There is a loop body - process all tuples and evaluate
22182236
* the body on each
@@ -2229,20 +2247,24 @@ pltcl_SPI_execp(ClientData cdata, Tcl_Interp *interp,
22292247
continue;
22302248
if (loop_rc == TCL_RETURN)
22312249
{
2250+
SPI_freetuptable(tuptable);
22322251
memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
22332252
return TCL_RETURN;
22342253
}
22352254
if (loop_rc == TCL_BREAK)
22362255
break;
2256+
SPI_freetuptable(tuptable);
22372257
memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
22382258
return TCL_ERROR;
22392259
}
22402260

2261+
SPI_freetuptable(tuptable);
2262+
22412263
/************************************************************
22422264
* Finally return the number of tuples
22432265
************************************************************/
22442266
memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
2245-
sprintf(buf, "%d", ntuples);
2267+
snprintf(buf, sizeof(buf), "%d", ntuples);
22462268
Tcl_SetResult(interp, buf, TCL_VOLATILE);
22472269
return TCL_OK;
22482270
}
@@ -2258,7 +2280,7 @@ pltcl_SPI_lastoid(ClientData cdata, Tcl_Interp *interp,
22582280
{
22592281
char buf[64];
22602282

2261-
sprintf(buf, "%u", SPI_lastoid);
2283+
snprintf(buf, sizeof(buf), "%u", SPI_lastoid);
22622284
Tcl_SetResult(interp, buf, TCL_VOLATILE);
22632285
return TCL_OK;
22642286
}
@@ -2300,7 +2322,7 @@ pltcl_set_tuple_values(Tcl_Interp *interp, char *arrayname,
23002322
{
23012323
arrptr = &arrayname;
23022324
nameptr = &attname;
2303-
sprintf(buf, "%d", tupno);
2325+
snprintf(buf, sizeof(buf), "%d", tupno);
23042326
Tcl_SetVar2(interp, arrayname, ".tupno", buf, 0);
23052327
}
23062328

0 commit comments

Comments
 (0)