aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Bennett <steveb@workware.net.au>2012-03-13 11:12:00 +1000
committerSteve Bennett <steveb@workware.net.au>2012-03-13 11:58:33 +1000
commit50d6304037f9d77c96c2ddecc4bfacf3fa289f84 (patch)
tree95313708ab24b66b57d9f66d513f3bf06a698ed3
parentb6c95fe34a5fa3b30e1f3f2fd3dc43be5414460a (diff)
downloadjimtcl-50d6304037f9d77c96c2ddecc4bfacf3fa289f84.zip
jimtcl-50d6304037f9d77c96c2ddecc4bfacf3fa289f84.tar.gz
jimtcl-50d6304037f9d77c96c2ddecc4bfacf3fa289f84.tar.bz2
Fix a reference counting bug
Ensure that the internal rep of interp->emptyObj is never changed to a script, since scripts use emptyObj as the source filename when no source info is available. Instead use a special nullScriptObj for this purpose. Signed-off-by: Steve Bennett <steveb@workware.net.au>
-rw-r--r--jim.c14
-rw-r--r--jim.h1
-rw-r--r--regtest.tcl6
3 files changed, 17 insertions, 4 deletions
diff --git a/jim.c b/jim.c
index b24b805..d440539 100644
--- a/jim.c
+++ b/jim.c
@@ -2994,7 +2994,7 @@ void FreeSourceInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
void DupSourceInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
{
- dupPtr->internalRep = srcPtr->internalRep;
+ dupPtr->internalRep.sourceValue = srcPtr->internalRep.sourceValue;
Jim_IncrRefCount(dupPtr->internalRep.sourceValue.fileNameObj);
}
@@ -3002,7 +3002,7 @@ static void JimSetSourceInfo(Jim_Interp *interp, Jim_Obj *objPtr,
Jim_Obj *fileNameObj, int lineNumber)
{
JimPanic((Jim_IsShared(objPtr), "JimSetSourceInfo called with shared object"));
- JimPanic((objPtr->typePtr != NULL, "JimSetSourceInfo called with typePtr != NULL"));
+ JimPanic((objPtr->typePtr == &sourceObjType, "JimSetSourceInfo called with non-source object"));
Jim_IncrRefCount(fileNameObj);
objPtr->internalRep.sourceValue.fileNameObj = fileNameObj;
objPtr->internalRep.sourceValue.lineNumber = lineNumber;
@@ -3499,9 +3499,12 @@ static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct J
ScriptObj *Jim_GetScript(Jim_Interp *interp, Jim_Obj *objPtr)
{
- struct ScriptObj *script = Jim_GetIntRepPtr(objPtr);
+ if (objPtr == interp->emptyObj) {
+ /* Avoid converting emptyObj to a script. use nullScriptObj instead. */
+ objPtr = interp->nullScriptObj;
+ }
- if (objPtr->typePtr != &scriptObjType || script->substFlags) {
+ if (objPtr->typePtr != &scriptObjType || ((struct ScriptObj *)Jim_GetIntRepPtr(objPtr))->substFlags) {
SetScriptFromAny(interp, objPtr, NULL);
}
return (ScriptObj *) Jim_GetIntRepPtr(objPtr);
@@ -5256,12 +5259,14 @@ Jim_Interp *Jim_CreateInterp(void)
i->unknown = Jim_NewStringObj(i, "unknown", -1);
i->errorProc = i->emptyObj;
i->currentScriptObj = Jim_NewEmptyStringObj(i);
+ i->nullScriptObj = Jim_NewEmptyStringObj(i);
Jim_IncrRefCount(i->emptyObj);
Jim_IncrRefCount(i->errorFileNameObj);
Jim_IncrRefCount(i->result);
Jim_IncrRefCount(i->stackTrace);
Jim_IncrRefCount(i->unknown);
Jim_IncrRefCount(i->currentScriptObj);
+ Jim_IncrRefCount(i->nullScriptObj);
Jim_IncrRefCount(i->errorProc);
Jim_IncrRefCount(i->trueObj);
Jim_IncrRefCount(i->falseObj);
@@ -5295,6 +5300,7 @@ void Jim_FreeInterp(Jim_Interp *i)
Jim_DecrRefCount(i, i->unknown);
Jim_DecrRefCount(i, i->errorFileNameObj);
Jim_DecrRefCount(i, i->currentScriptObj);
+ Jim_DecrRefCount(i, i->nullScriptObj);
Jim_FreeHashTable(&i->commands);
#ifdef JIM_REFERENCES
Jim_FreeHashTable(&i->references);
diff --git a/jim.h b/jim.h
index 0204090..0f24a02 100644
--- a/jim.h
+++ b/jim.h
@@ -540,6 +540,7 @@ typedef struct Jim_Interp {
Jim_Obj *liveList; /* Linked list of all the live objects. */
Jim_Obj *freeList; /* Linked list of all the unused objects. */
Jim_Obj *currentScriptObj; /* Script currently in execution. */
+ Jim_Obj *nullScriptObj; /* script representation of an empty string */
Jim_Obj *emptyObj; /* Shared empty string object. */
Jim_Obj *trueObj; /* Shared true int object. */
Jim_Obj *falseObj; /* Shared false int object. */
diff --git a/regtest.tcl b/regtest.tcl
index d144152..2f09700 100644
--- a/regtest.tcl
+++ b/regtest.tcl
@@ -204,6 +204,12 @@ catch {
}
puts "TEST 28 PASSED"
+# REGTEST 29
+# Reference counting problem at exit
+set x [lindex {} 0]
+info source $x
+eval $x
+
# TAKE THE FOLLOWING puts AS LAST LINE
puts "--- ALL TESTS PASSED ---"