Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | * generic/tclProc.c (ProcCompileProc): When a bump of the compile epoch forces the re-compile of a proc body, take care not to overwrite any Proc struct that may be referred to on the active call stack. This fixes [Bug 148218]. Note that the fix will not be effective for code that calls the private routine TclProcCompileProc() directly. |
|---|---|
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA1: |
befd37911b2ab329bf62bcadfab5a2cc |
| User & Date: | dgp 2006-05-13 17:14:26.000 |
Context
|
2006-05-15
| ||
| 16:07 | Silence compiler warning. check-in: 62f90c522c user: dgp tags: trunk | |
|
2006-05-13
| ||
| 17:14 | * generic/tclProc.c (ProcCompileProc): When a bump of the compile epoch forces the ... check-in: befd37911b user: dgp tags: trunk | |
|
2006-05-12
| ||
| 18:12 | * generic/tclEvent.c (HandleBgErrors): fix leak. [Coverity issue 86] check-in: 39f2094997 user: das tags: trunk | |
Changes
Changes to ChangeLog.
1 2 3 4 5 6 7 | 2006-05-13 Daniel Steffen <das@users.sourceforge.net> * generic/tclEvent.c (HandleBgErrors): fix leak. [Coverity issue 86] 2006-05-05 Don Porter <dgp@users.sourceforge.net> * generic/tclMain.c (Tcl_Main): Corrected flaw that required | > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 2006-05-13 Don Porter <dgp@users.sourceforge.net> * generic/tclProc.c (ProcCompileProc): When a bump of the compile epoch forces the re-compile of a proc body, take care not to overwrite any Proc struct that may be referred to on the active call stack. This fixes [Bug 148218]. Note that the fix will not be effective for code that calls the private routine TclProcCompileProc() directly. 2006-05-13 Daniel Steffen <das@users.sourceforge.net> * generic/tclEvent.c (HandleBgErrors): fix leak. [Coverity issue 86] 2006-05-05 Don Porter <dgp@users.sourceforge.net> * generic/tclMain.c (Tcl_Main): Corrected flaw that required |
| ︙ | ︙ |
Changes to generic/tclProc.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* * tclProc.c -- * * This file contains routines that implement Tcl procedures, including * the "proc" and "uplevel" commands. * * Copyright (c) 1987-1993 The Regents of the University of California. * Copyright (c) 1994-1998 Sun Microsystems, Inc. * Copyright (c) 2004-2006 Miguel Sofer * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* * tclProc.c -- * * This file contains routines that implement Tcl procedures, including * the "proc" and "uplevel" commands. * * Copyright (c) 1987-1993 The Regents of the University of California. * Copyright (c) 1994-1998 Sun Microsystems, Inc. * Copyright (c) 2004-2006 Miguel Sofer * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * * RCS: @(#) $Id: tclProc.c,v 1.90 2006/05/13 17:14:26 dgp Exp $ */ #include "tclInt.h" #include "tclCompile.h" /* * Prototypes for static functions in this file |
| ︙ | ︙ | |||
33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
static void ProcBodyDup(Tcl_Obj *srcPtr, Tcl_Obj *dupPtr);
static void ProcBodyFree(Tcl_Obj *objPtr);
static int ProcessProcResultCode(Tcl_Interp *interp,
char *procName, int nameLen, int returnCode);
static int SetLambdaFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
static int TclCompileNoOp(Tcl_Interp *interp, Tcl_Parse *parsePtr,
struct CompileEnv *envPtr);
/*
* The ProcBodyObjType type
*/
Tcl_ObjType tclProcBodyType = {
"procbody", /* name for this type */
| > > > > | 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
static void ProcBodyDup(Tcl_Obj *srcPtr, Tcl_Obj *dupPtr);
static void ProcBodyFree(Tcl_Obj *objPtr);
static int ProcessProcResultCode(Tcl_Interp *interp,
char *procName, int nameLen, int returnCode);
static int SetLambdaFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
static int TclCompileNoOp(Tcl_Interp *interp, Tcl_Parse *parsePtr,
struct CompileEnv *envPtr);
static int ProcCompileProc (Tcl_Interp *interp, Proc *procPtr,
Tcl_Obj *bodyPtr, Namespace *nsPtr,
CONST char *description, CONST char *procName,
Proc **procPtrPtr);
/*
* The ProcBodyObjType type
*/
Tcl_ObjType tclProcBodyType = {
"procbody", /* name for this type */
|
| ︙ | ︙ | |||
1152 1153 1154 1155 1156 1157 1158 |
* invoked. */
int objc, /* Count of number of arguments to this
* procedure. */
Tcl_Obj *CONST objv[], /* Argument value objects. */
int skip) /* Number of initial arguments to be skipped,
* ie, words in the "command name" */
{
| | | 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 |
* invoked. */
int objc, /* Count of number of arguments to this
* procedure. */
Tcl_Obj *CONST objv[], /* Argument value objects. */
int skip) /* Number of initial arguments to be skipped,
* ie, words in the "command name" */
{
Proc *procPtr = (Proc *) clientData;
Namespace *nsPtr = procPtr->cmdPtr->nsPtr;
CallFrame *framePtr, **framePtrPtr;
register Var *varPtr;
register CompiledLocal *localPtr;
char *procName;
int nameLen, localCt, numArgs, argCt, i, imax, result;
Var *compiledLocals;
|
| ︙ | ︙ | |||
1175 1176 1177 1178 1179 1180 1181 |
/*
* If necessary, compile the procedure's body. The compiler will allocate
* frame slots for the procedure's non-argument local variables. Note that
* compiling the body might increase procPtr->numCompiledLocals if new
* local variables are found while compiling.
*/
| | | | 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 |
/*
* If necessary, compile the procedure's body. The compiler will allocate
* frame slots for the procedure's non-argument local variables. Note that
* compiling the body might increase procPtr->numCompiledLocals if new
* local variables are found while compiling.
*/
result = ProcCompileProc(interp, procPtr, procPtr->bodyPtr, nsPtr,
"body of proc", procName, &procPtr);
if (result != TCL_OK) {
return result;
}
/*
|
| ︙ | ︙ | |||
1471 1472 1473 1474 1475 1476 1477 1478 |
Tcl_Obj *bodyPtr, /* Body of proc. (Usually procPtr->bodyPtr,
* but could be any code fragment compiled in
* the context of this procedure.) */
Namespace *nsPtr, /* Namespace containing procedure. */
CONST char *description, /* string describing this body of code. */
CONST char *procName) /* Name of this procedure. */
{
Interp *iPtr = (Interp*)interp;
| > > > > > > > > > > > > > > > > > | > | 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 |
Tcl_Obj *bodyPtr, /* Body of proc. (Usually procPtr->bodyPtr,
* but could be any code fragment compiled in
* the context of this procedure.) */
Namespace *nsPtr, /* Namespace containing procedure. */
CONST char *description, /* string describing this body of code. */
CONST char *procName) /* Name of this procedure. */
{
return ProcCompileProc(interp, procPtr, bodyPtr, nsPtr, description,
procName, NULL);
}
static int
ProcCompileProc(
Tcl_Interp *interp, /* Interpreter containing procedure. */
Proc *procPtr, /* Data associated with procedure. */
Tcl_Obj *bodyPtr, /* Body of proc. (Usually procPtr->bodyPtr,
* but could be any code fragment compiled in
* the context of this procedure.) */
Namespace *nsPtr, /* Namespace containing procedure. */
CONST char *description, /* string describing this body of code. */
CONST char *procName, /* Name of this procedure. */
Proc **procPtrPtr) /* Points to storage where a replacement
* (Proc *) value may be written. */
{
Interp *iPtr = (Interp*)interp;
int i, result;
Tcl_CallFrame *framePtr;
Proc *saveProcPtr;
ByteCode *codePtr = (ByteCode *) bodyPtr->internalRep.otherValuePtr;
CompiledLocal *localPtr;
/*
* If necessary, compile the procedure's body. The compiler will allocate
* frame slots for the procedure's non-argument local variables. If the
* ByteCode already exists, make sure it hasn't been invalidated by
* someone redefining a core command (this might make the compiled code
* wrong). Also, if the code was compiled in/for a different interpreter,
|
| ︙ | ︙ | |||
1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 |
*
* TRICKY NOTE: Be careful to push a call frame with the proper
* namespace context, so that the byte codes are compiled in the
* appropriate class context.
*/
saveProcPtr = iPtr->compiledProcPtr;
iPtr->compiledProcPtr = procPtr;
result = TclPushStackFrame(interp, &framePtr,
(Tcl_Namespace *) nsPtr, /* isProcCallFrame */ 0);
if (result == TCL_OK) {
result = tclByteCodeType.setFromAnyProc(interp, bodyPtr);
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 |
*
* TRICKY NOTE: Be careful to push a call frame with the proper
* namespace context, so that the byte codes are compiled in the
* appropriate class context.
*/
saveProcPtr = iPtr->compiledProcPtr;
if (procPtrPtr != NULL && procPtr->refCount > 1) {
Tcl_Command token;
Tcl_CmdInfo info;
Proc *new = (Proc *) ckalloc(sizeof(Proc));
new->iPtr = procPtr->iPtr;
new->refCount = 1;
token = (Tcl_Command) new->cmdPtr = procPtr->cmdPtr;
new->bodyPtr = Tcl_DuplicateObj(bodyPtr);
bodyPtr = new->bodyPtr;
Tcl_IncrRefCount(bodyPtr);
new->numArgs = procPtr->numArgs;
new->numCompiledLocals = new->numArgs;
new->firstLocalPtr = NULL;
new->lastLocalPtr = NULL;
localPtr = procPtr->firstLocalPtr;
for (i = 0; i < new->numArgs; i++, localPtr = localPtr->nextPtr) {
CompiledLocal *copy = (CompiledLocal *) ckalloc((unsigned)
(sizeof(CompiledLocal) -sizeof(localPtr->name)
+ localPtr->nameLength + 1));
if (new->firstLocalPtr == NULL) {
new->firstLocalPtr = new->lastLocalPtr = copy;
} else {
new->lastLocalPtr->nextPtr = copy;
new->lastLocalPtr = copy;
}
copy->nextPtr = NULL;
copy->nameLength = localPtr->nameLength;
copy->frameIndex = localPtr->frameIndex;
copy->flags = localPtr->flags;
copy->defValuePtr = localPtr->defValuePtr;
if (copy->defValuePtr) {
Tcl_IncrRefCount(copy->defValuePtr);
}
copy->resolveInfo = localPtr->resolveInfo;
strcpy(copy->name, localPtr->name);
}
/* Reset the ClientData */
Tcl_GetCommandInfoFromToken(token, &info);
if (info.objClientData == (ClientData) procPtr) {
info.objClientData = (ClientData) new;
}
if (info.clientData == (ClientData) procPtr) {
info.clientData = (ClientData) new;
}
if (info.deleteData == (ClientData) procPtr) {
info.deleteData = (ClientData) new;
}
Tcl_SetCommandInfoFromToken(token, &info);
procPtr->refCount--;
*procPtrPtr = procPtr = new;
}
iPtr->compiledProcPtr = procPtr;
result = TclPushStackFrame(interp, &framePtr,
(Tcl_Namespace *) nsPtr, /* isProcCallFrame */ 0);
if (result == TCL_OK) {
result = tclByteCodeType.setFromAnyProc(interp, bodyPtr);
|
| ︙ | ︙ |