summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--generic/tclBasic.c26
-rw-r--r--tests/basic.test20
3 files changed, 47 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index 912d754..55443b0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2005-02-10 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclBasic.c (Tcl_EvalObjEx):
+ * tests/basic.test (basic-26.2): preserve the arguments passed to
+ TEOV in the pure-list branch, in case the list shimmers away. Fix
+ for [Bug 1119369], reported by Peter MacDonald.
+
2005-02-10 Vince Darley <vincentdarley@users.sourceforge.net>
* generic/tclFileName.c: fix for test failures introduced
diff --git a/generic/tclBasic.c b/generic/tclBasic.c
index 1d2c77f..086dfa9 100644
--- a/generic/tclBasic.c
+++ b/generic/tclBasic.c
@@ -13,7 +13,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclBasic.c,v 1.140 2005/01/28 01:49:50 hobbs Exp $
+ * RCS: @(#) $Id: tclBasic.c,v 1.141 2005/02/10 19:08:12 msofer Exp $
*/
#include "tclInt.h"
@@ -3754,11 +3754,27 @@ Tcl_EvalObjEx(interp, objPtr, flags)
* everything into a string and back out again.
*/
if ((objPtr->typePtr == &tclListType) && /* is a list... */
- (objPtr->bytes == NULL) /* ...without a string rep */) {
- register List *listRepPtr =
+ (objPtr->bytes == NULL) /* ...without a string rep */) {
+ List *listRepPtr =
(List *) objPtr->internalRep.twoPtrValue.ptr1;
- result = Tcl_EvalObjv(interp, listRepPtr->elemCount,
- listRepPtr->elements, flags);
+ int i, objc = listRepPtr->elemCount;
+ Tcl_Obj **objv;
+
+ /*
+ * Copy the list elements here, to avoid a segfault if objPtr
+ * loses its List internal rep [Bug 1119369]
+ */
+
+ objv = (Tcl_Obj **) TclStackAlloc(interp, objc*sizeof(Tcl_Obj *));
+ for (i=0; i < objc; i++) {
+ objv[i] = listRepPtr->elements[i];
+ Tcl_IncrRefCount(objv[i]);
+ }
+ result = Tcl_EvalObjv(interp, objc, objv, flags);
+ for (i=0; i < objc; i++) {
+ TclDecrRefCount(objv[i]);
+ }
+ TclStackFree(interp);
} else {
script = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
result = Tcl_EvalEx(interp, script, numSrcBytes, flags);
diff --git a/tests/basic.test b/tests/basic.test
index da5449b..7a4b58d 100644
--- a/tests/basic.test
+++ b/tests/basic.test
@@ -15,7 +15,7 @@
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
-# RCS: @(#) $Id: basic.test,v 1.36 2004/11/18 19:22:12 dgp Exp $
+# RCS: @(#) $Id: basic.test,v 1.37 2005/02/10 19:08:12 msofer Exp $
#
package require tcltest 2
@@ -438,6 +438,24 @@ test basic-26.1 {Tcl_EvalObj: preserve object while evaling it} -setup {
rename myHandler {}
} -result "foo\n while executing\n\"error foo\""
+test basic-26.2 {Tcl_EvalObjEx, pure-list branch: preserve "objv"} {
+ #
+ # Follow the pure-list branch in a manner that
+ # a - the pure-list internal rep is destroyed by shimmering
+ # b - the command returns an error
+ # As the error code in Tcl_EvalObjv accesses the list elements, this will
+ # cause a segfault if [Bug 1119369] has not been fixed.
+ #
+
+ set SRC [list foo 1] ;# pure-list command
+ proc foo str {
+ # Shimmer pure-list to cmdName, cleanup and error
+ proc $::SRC {} {}; $::SRC
+ error "BAD CALL"
+ }
+ catch {eval $SRC}
+} 1
+
test basic-27.1 {Tcl_ExprLong} {emptyTest} {
} {}