diff options
author | andy <andrew.m.goth@gmail.com> | 2017-04-15 15:15:59 (GMT) |
---|---|---|
committer | andy <andrew.m.goth@gmail.com> | 2017-04-15 15:15:59 (GMT) |
commit | c01a4f250b3648cd5794ce7c468af5c764a848cd (patch) | |
tree | 04893e41c70fae65b7e72d7b283cdf5f84e18e2a | |
parent | 770385938d96796e61dfc637ee9e648891b47497 (diff) | |
download | tcl-amg_array_enum_c_api.zip tcl-amg_array_enum_c_api.tar.gz tcl-amg_array_enum_c_api.tar.bz2 |
Check in stash. This code probably does not compile as-is. Changes intended to address possible segfault on termination of search.amg_array_enum_c_api
-rw-r--r-- | generic/tclVar.c | 40 |
1 files changed, 28 insertions, 12 deletions
diff --git a/generic/tclVar.c b/generic/tclVar.c index 10fe836..1f01dd5 100644 --- a/generic/tclVar.c +++ b/generic/tclVar.c @@ -191,7 +191,12 @@ enum { typedef struct Tcl_ArraySearch_ ArraySearch; struct Tcl_ArraySearch_ { - Tcl_Obj *name; /* Name of this search */ + Tcl_Obj *name; /* Name of this search. NULL if this search was + * created by Tcl_ArraySearchStart() rather than + * the [array startsearch] command. This is done + * to prevent C-initiated searches from being + * accessed via Tcl commands since they have + * different memory management semantics. */ int id; /* Integer id used to distinguish among * multiple concurrent searches for the same * array. */ @@ -1522,7 +1527,9 @@ void ArraySearchFree( ArraySearch *searchPtr) /* Array enumeration state structure. */ { - Tcl_DecrRefCount(searchPtr->name); + if (searchPtr->name) { + Tcl_DecrRefCount(searchPtr->name); + } Tcl_DecrRefCount(searchPtr->varNameObj); if (searchPtr->filterObj) { Tcl_DecrRefCount(searchPtr->filterObj); @@ -2351,18 +2358,19 @@ Tcl_ArraySearchStart( return NULL; } + search.nextEntry = ArrayFirst(interp, &search, &fail); + if (!search.nextEntry && fail) { + return NULL; + } + search.name = NULL; search.varNameObj = part1Ptr; search.varPtr = varPtr; search.filterObj = part2Ptr; search.filterType = flags & TCL_MATCH; - search.nextEntry = ArrayFirst(interp, &search, &fail); search.flags = KEEP_ON_ABORT; - if (!search.nextEntry && fail) { - return NULL; - } /* - * Make a new array search with a free name. + * Make a new array search. */ hPtr = Tcl_CreateHashEntry(&iPtr->varSearches, varPtr, &isNew); @@ -2374,8 +2382,6 @@ Tcl_ArraySearchStart( search.id = ((ArraySearch *)Tcl_GetHashValue(hPtr))->id + 1; search.nextPtr = Tcl_GetHashValue(hPtr); } - search.name = Tcl_ObjPrintf("s-%d-%s", search.id, TclGetString(part1Ptr)); - Tcl_IncrRefCount(search.name); Tcl_IncrRefCount(search.varNameObj); if (part2Ptr) { Tcl_IncrRefCount(part2Ptr); @@ -4255,7 +4261,7 @@ ArrayStartSearchCmd( int objc, Tcl_Obj *const objv[]) { - Tcl_Obj *varNameObj, *filterObj; + Tcl_Obj *varNameObj, *filterObj, *tokenObj; ArraySearch *searchPtr; int filterType; @@ -4270,6 +4276,15 @@ ArrayStartSearchCmd( } /* + * Give the search a name so it can be looked up by other array commands. + */ + + tokenObj = Tcl_ObjPrintf("s-%d-%s", searchPtr->id, + TclGetString(varNameObj)); + searchPtr->name = tokenObj; + Tcl_IncrRefCount(tokenObj); + + /* * Clear the KEEP_ON_ABORT flag which was set by Tcl_ArraySearchStart() so * the search structure will automatically be deallocated should the search * terminate early due to array elements being added or removed or the array @@ -4278,7 +4293,7 @@ ArrayStartSearchCmd( searchPtr->flags = 0; - Tcl_SetObjResult(interp, searchPtr->name); + Tcl_SetObjResult(interp, tokenObj); return TCL_OK; } @@ -5656,7 +5671,8 @@ ParseSearchId( /* Fallback: do string compares. */ for (searchPtr = Tcl_GetHashValue(hPtr); searchPtr != NULL; searchPtr = searchPtr->nextPtr) { - if (strcmp(TclGetString(searchPtr->name), handle) == 0) { + if (searchPtr->name + && strcmp(TclGetString(searchPtr->name), handle) == 0) { return searchPtr; } } |