summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordkf <donal.k.fellows@manchester.ac.uk>2016-06-23 08:21:42 (GMT)
committerdkf <donal.k.fellows@manchester.ac.uk>2016-06-23 08:21:42 (GMT)
commite577cd8cf8ba504129e0b4ca6e698e442e55eacb (patch)
treea1782bd818ef484be2537ef6d84f6a6f11048537
parentff29c56ea43cdd5088f90248e320b1cfc28b2cc1 (diff)
parentf05e2297802cbc2f12f67acb22ca3680f36d38c8 (diff)
downloadtcl-e577cd8cf8ba504129e0b4ca6e698e442e55eacb.zip
tcl-e577cd8cf8ba504129e0b4ca6e698e442e55eacb.tar.gz
tcl-e577cd8cf8ba504129e0b4ca6e698e442e55eacb.tar.bz2
[d553228d9f] Stop crashes in [dict update] with low refcount dictionaries.
-rw-r--r--generic/tclExecute.c4
-rw-r--r--tests/dict.test7
2 files changed, 11 insertions, 0 deletions
diff --git a/generic/tclExecute.c b/generic/tclExecute.c
index cd28a92..3f57333 100644
--- a/generic/tclExecute.c
+++ b/generic/tclExecute.c
@@ -7706,6 +7706,7 @@ TEBCresume(
goto gotError;
}
}
+ Tcl_IncrRefCount(dictPtr);
if (TclListObjGetElements(interp, OBJ_AT_TOS, &length,
&keyPtrPtr) != TCL_OK) {
TRACE_ERROR(interp);
@@ -7718,6 +7719,7 @@ TEBCresume(
if (Tcl_DictObjGet(interp, dictPtr, keyPtrPtr[i],
&valuePtr) != TCL_OK) {
TRACE_ERROR(interp);
+ Tcl_DecrRefCount(dictPtr);
goto gotError;
}
varPtr = LOCAL(duiPtr->varIndices[i]);
@@ -7734,10 +7736,12 @@ TEBCresume(
duiPtr->varIndices[i]) == NULL) {
CACHE_STACK_INFO();
TRACE_ERROR(interp);
+ Tcl_DecrRefCount(dictPtr);
goto gotError;
}
CACHE_STACK_INFO();
}
+ TclDecrRefCount(dictPtr);
TRACE_APPEND(("OK\n"));
NEXT_INST_F(9, 0, 0);
diff --git a/tests/dict.test b/tests/dict.test
index d5406d0..a6b0cb4 100644
--- a/tests/dict.test
+++ b/tests/dict.test
@@ -2048,6 +2048,13 @@ test dict-24.25 {dict map with huge dict (compiled)} {
}} 100000
} 166666666600000
+test dict-25.1 {compiled dict update with low-refcount values [Bug d553228d9f]} {
+ # Test crashes on failure
+ apply {{} {
+ lassign {} item
+ dict update item item item two two {}
+ }}
+} {}
# cleanup
::tcltest::cleanupTests