From 07e0b116171eb0e1b10cd691be7995103106a174 Mon Sep 17 00:00:00 2001 From: Miguel Sofer Date: Thu, 10 Feb 2005 18:58:30 +0000 Subject: * 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. --- ChangeLog | 7 +++++++ generic/tclBasic.c | 23 ++++++++++++++++++++--- tests/basic.test | 20 +++++++++++++++++++- 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 76e0127..d6ee926 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2005-02-10 Miguel Sofer + + * 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 Donal K. Fellows * doc/binary.n: Made the documentation of sign bit masking and diff --git a/generic/tclBasic.c b/generic/tclBasic.c index 9d6255c..ea3bdf8 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.75.2.11 2005/01/28 01:50:26 hobbs Exp $ + * RCS: @(#) $Id: tclBasic.c,v 1.75.2.12 2005/02/10 18:58:35 msofer Exp $ */ #include "tclInt.h" @@ -4003,8 +4003,25 @@ Tcl_EvalObjEx(interp, objPtr, flags) (objPtr->bytes == NULL) /* ...without a string rep */) { register List *listRepPtr = (List *) objPtr->internalRep.twoPtrValue.ptr1; - result = Tcl_EvalObjv(interp, listRepPtr->elemCount, - listRepPtr->elements, flags); + int i, objc = listRepPtr->elemCount; +#define TEOE_PREALLOC 10 + Tcl_Obj *staticObjv[TEOE_PREALLOC], **objv = staticObjv; + + if (objc > TEOE_PREALLOC) { + objv = (Tcl_Obj **) ckalloc(objc*sizeof(Tcl_Obj *)); + } +#undef TEOE_PREALLOC + 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]); + } + if (objv != staticObjv) { + ckfree((char *) objv); + } } else { script = Tcl_GetStringFromObj(objPtr, &numSrcBytes); result = Tcl_EvalEx(interp, script, numSrcBytes, flags); diff --git a/tests/basic.test b/tests/basic.test index 294746f..2c8a6a7 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.25.2.5 2004/10/26 20:14:32 dgp Exp $ +# RCS: @(#) $Id: basic.test,v 1.25.2.6 2005/02/10 18:58:36 msofer Exp $ # package require tcltest 2 @@ -432,6 +432,24 @@ test basic-26.1 {Tcl_EvalObj: preserve object while evaling it} { set x } "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} { } {} -- cgit v0.12