summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsebres <sebres@users.sourceforge.net>2022-07-27 15:48:13 (GMT)
committersebres <sebres@users.sourceforge.net>2022-07-27 15:48:13 (GMT)
commitcf9f33de53a5c07f902ad314bf150e3385b1184f (patch)
tree311042757f18bdc464157ae07f0952e2e3b90c26
parent63adb899254988e8a74db9709014c14c17cdc970 (diff)
parent856edbc25be9401b87ea00c346b7bea728e8c0dd (diff)
downloadtcl-cf9f33de53a5c07f902ad314bf150e3385b1184f.zip
tcl-cf9f33de53a5c07f902ad314bf150e3385b1184f.tar.gz
tcl-cf9f33de53a5c07f902ad314bf150e3385b1184f.tar.bz2
cherry-pick branch apn-apply-bug (only test without the fix) to 8.6
-rw-r--r--generic/tclTest.c84
-rw-r--r--tests/apply.test11
2 files changed, 94 insertions, 1 deletions
diff --git a/generic/tclTest.c b/generic/tclTest.c
index 88e32bc..0004c8e 100644
--- a/generic/tclTest.c
+++ b/generic/tclTest.c
@@ -329,6 +329,7 @@ static Tcl_ObjCmdProc TestInterpResolverCmd;
#if defined(HAVE_CPUID) && !defined(MAC_OSX_TCL)
static Tcl_ObjCmdProc TestcpuidCmd;
#endif
+static Tcl_ObjCmdProc TestApplyLambdaObjCmd;
static const Tcl_Filesystem testReportingFilesystem = {
"reporting",
@@ -615,6 +616,8 @@ Tcltest_Init(
NULL, NULL);
Tcl_CreateObjCommand(interp, "testinterpresolver", TestInterpResolverCmd,
NULL, NULL);
+ Tcl_CreateObjCommand(interp, "testapplylambda", TestApplyLambdaObjCmd,
+ NULL, NULL);
if (TclObjTest_Init(interp) != TCL_OK) {
return TCL_ERROR;
@@ -7806,7 +7809,85 @@ TestInterpResolverCmd(
}
return TCL_OK;
}
-
+
+/*
+ *------------------------------------------------------------------------
+ *
+ * TestApplyLambdaObjCmd --
+ *
+ * Implements the Tcl command testapplylambda. This tests the apply
+ * implementation handling of a lambda where the lambda has a list
+ * internal representation where the second element's internal
+ * representation is already a byte code object.
+ *
+ * Results:
+ * TCL_OK - Success. Caller should check result is 42
+ * TCL_ERROR - Error.
+ *
+ * Side effects:
+ * In the presence of the apply bug, may panic. Otherwise
+ * Interpreter result holds result or error message.
+ *
+ *------------------------------------------------------------------------
+ */
+int TestApplyLambdaObjCmd (
+ ClientData notUsed,
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ Tcl_Obj *lambdaObjs[2];
+ Tcl_Obj *evalObjs[2];
+ Tcl_Obj *lambdaObj;
+ int result;
+
+ /* Create a lambda {{} {set a 42}} */
+ lambdaObjs[0] = Tcl_NewObj(); /* No parameters */
+ lambdaObjs[1] = Tcl_NewStringObj("set a 42", -1); /* Body */
+ lambdaObj = Tcl_NewListObj(2, lambdaObjs);
+ Tcl_IncrRefCount(lambdaObj);
+
+ /* Create the command "apply {{} {set a 42}" */
+ evalObjs[0] = Tcl_NewStringObj("apply", -1);
+ Tcl_IncrRefCount(evalObjs[0]);
+ /*
+ * NOTE: IMPORTANT TO EXHIBIT THE BUG. We duplicate the lambda because
+ * it will get shimmered to a Lambda internal representation but we
+ * want to hold on to our list representation.
+ */
+ evalObjs[1] = Tcl_DuplicateObj(lambdaObj);
+ Tcl_IncrRefCount(evalObjs[1]);
+
+ /* Evaluate it */
+ result = Tcl_EvalObjv(interp, 2, evalObjs, TCL_EVAL_GLOBAL);
+ if (result != TCL_OK) {
+ Tcl_DecrRefCount(evalObjs[0]);
+ Tcl_DecrRefCount(evalObjs[1]);
+ return result;
+ }
+ /*
+ * So far so good. At this point,
+ * - evalObjs[1] has an internal representation of Lambda
+ * - lambdaObj[1] ({set a 42}) has been shimmered to
+ * an internal representation of ByteCode.
+ */
+ Tcl_DecrRefCount(evalObjs[1]); /* Don't need this anymore */
+ /*
+ * The bug trigger. Repeating the command but:
+ * - we are calling apply with a lambda that is a list (as BEFORE),
+ * BUT
+ * - The body of the lambda (lambdaObjs[1]) ALREADY has internal
+ * representation of ByteCode and thus will not be compiled again
+ */
+ evalObjs[1] = lambdaObj; /* lambdaObj already has a ref count so
+ no need for IncrRef */
+ result = Tcl_EvalObjv(interp, 2, evalObjs, TCL_EVAL_GLOBAL);
+ Tcl_DecrRefCount(evalObjs[0]);
+ Tcl_DecrRefCount(lambdaObj);
+
+ return result;
+}
+
/*
* Local Variables:
* mode: c
@@ -7816,3 +7897,4 @@ TestInterpResolverCmd(
* indent-tabs-mode: nil
* End:
*/
+
diff --git a/tests/apply.test b/tests/apply.test
index 8696245..1a3c96d 100644
--- a/tests/apply.test
+++ b/tests/apply.test
@@ -16,12 +16,16 @@ if {"::tcltest" ni [namespace children]} {
package require tcltest 2.5
namespace import -force ::tcltest::*
}
+::tcltest::loadTestedCommands
+catch [list package require -exact tcl::test [info patchlevel]]
if {[info commands ::apply] eq {}} {
return
}
testConstraint memory [llength [info commands memory]]
+testConstraint applylambda [llength [info commands testapplylambda]]
+
# Tests for wrong number of arguments
@@ -306,6 +310,13 @@ test apply-9.3 {leaking internal rep} -setup {
unset -nocomplain end i x tmp leakedBytes
} -result 0
+# Tests for specific bugs
+test apply-10.1 {Test for precompiled bytecode body} -constraints {
+ applylambda
+} -body {
+ testapplylambda
+} -result 42
+
# Tests for the avoidance of recompilation
# cleanup