summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorandy <andrew.m.goth@gmail.com>2016-12-25 00:23:21 (GMT)
committerandy <andrew.m.goth@gmail.com>2016-12-25 00:23:21 (GMT)
commit14ff1705d414d9d1f5be2d0bb3d8b384c0eb4717 (patch)
tree46b3786105ed8a0344fee8d37aaf428555960d8e
parent7fe6eb2132c91bfbdef212a8d687868a1393df03 (diff)
downloadtcl-14ff1705d414d9d1f5be2d0bb3d8b384c0eb4717.zip
tcl-14ff1705d414d9d1f5be2d0bb3d8b384c0eb4717.tar.gz
tcl-14ff1705d414d9d1f5be2d0bb3d8b384c0eb4717.tar.bz2
Do not deallocate Tcl_ArraySearchStart()-initiated array searches when Tcl_ArraySearchPeek() or Tcl_ArraySearchNext() is called, only when Tcl_ArraySearchDone() is called. This avoids a crash should user code unconditionally call Tcl_ArraySearchDone() at the end of an array enumeration loop. This change does not affect array searches initiated by the Tcl script command [array startsearch].
-rw-r--r--generic/tclVar.c24
1 files changed, 14 insertions, 10 deletions
diff --git a/generic/tclVar.c b/generic/tclVar.c
index 742e18a..10fe836 100644
--- a/generic/tclVar.c
+++ b/generic/tclVar.c
@@ -243,7 +243,7 @@ static Var * ArrayNext(Tcl_Interp *interp, ArraySearch *searchPtr,
int *failPtr);
static void ArrayDone(Tcl_Interp *interp, ArraySearch *searchPtr);
static int ArrayAborted(Tcl_Interp *interp,
- ArraySearch *searchPtr);
+ ArraySearch *searchPtr, int dealloc);
static void ArraySearchFree(ArraySearch *searchPtr);
static int ArrayNames(Tcl_Interp *interp, Var *varPtr,
Tcl_Obj *filterObj, int filterType,
@@ -1468,13 +1468,14 @@ ArrayDone(
*
* ArrayAborted --
*
- * Deallocates array searches if they aborted due to array elements being
- * added or removed or the array being unset.
+ * Checks if an array search was aborted due to array elements being added
+ * or removed or the array being unsed. Optionally deallocates it if so.
*
* Results:
* TCL_OK is returned if the array search did not abort. TCL_ERROR is
* returned if the array search did abort, and a message to that effect is
- * placed in the interpreter result.
+ * placed in the interpreter result. If the dealloc argument is nonzero,
+ * the array search is also deallocated if it aborted.
*
* Side effects:
* Memory used by the search may be released to the storage allocator.
@@ -1486,10 +1487,13 @@ int
ArrayAborted(
Tcl_Interp *interp, /* Command interpreter in which the array
* variable is located. */
- ArraySearch *searchPtr) /* Array enumeration state structure. */
+ ArraySearch *searchPtr, /* Array enumeration state structure. */
+ int dealloc) /* If nonzero, deallocate aborted searches. */
{
if (searchPtr->flags & SEARCH_ABORTED) {
- ArraySearchFree(searchPtr);
+ if (dealloc) {
+ ArraySearchFree(searchPtr);
+ }
Tcl_SetResult(interp, "search aborted due to array change", TCL_STATIC);
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAYSEARCH", "n/a", NULL);
return TCL_ERROR;
@@ -2416,10 +2420,10 @@ Tcl_ArraySearchPeek(
Tcl_Obj *keyObj, *valueObj;
/*
- * Deallocate aborted searches.
+ * Report aborted searches.
*/
- if (ArrayAborted(interp, search) != TCL_OK) {
+ if (ArrayAborted(interp, search, 0) != TCL_OK) {
return TCL_ERROR;
}
@@ -2548,10 +2552,10 @@ Tcl_ArraySearchDone(
Tcl_ArraySearch search) /* Prior return from Tcl_ArraySearchStart(). */
{
/*
- * Deallocate aborted searches.
+ * Report and deallocate aborted searches.
*/
- if (ArrayAborted(interp, search) != TCL_OK) {
+ if (ArrayAborted(interp, search, 1) != TCL_OK) {
return TCL_ERROR;
}