summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorapnadkarni <apnmbx-wits@yahoo.com>2023-07-16 07:23:13 (GMT)
committerapnadkarni <apnmbx-wits@yahoo.com>2023-07-16 07:23:13 (GMT)
commit7791d13f5c7e5c514bdce1e27760d30100e38375 (patch)
tree3577b39399916930e9b7e3d2538d59b913096f2a
parent56ca2a64d7665bc088790e6cfa134b39a7d0034f (diff)
parentccf857a3db566e41ba8167be6442441cdf92a9e3 (diff)
downloadtcl-7791d13f5c7e5c514bdce1e27760d30100e38375.zip
tcl-7791d13f5c7e5c514bdce1e27760d30100e38375.tar.gz
tcl-7791d13f5c7e5c514bdce1e27760d30100e38375.tar.bz2
Merge 8.7 - Bug [a366c6efee]
-rw-r--r--generic/tclInt.h4
-rw-r--r--generic/tclListObj.c15
-rw-r--r--tests/lreplace.test9
3 files changed, 21 insertions, 7 deletions
diff --git a/generic/tclInt.h b/generic/tclInt.h
index d7941fb..9c7ad17 100644
--- a/generic/tclInt.h
+++ b/generic/tclInt.h
@@ -2672,8 +2672,8 @@ typedef struct ListRep {
* (1) No string representation exists which means it will obviously have
* to be generated from the list representation when needed
* (2) The ListStore flags is marked canonical. This is done at the time
- * the string representation is generated from the list IF the list
- * representation does not have a span (see comments in UpdateStringOfList).
+ * the string representation is generated from the list under certain
+ * conditions (see comments in UpdateStringOfList).
* (3) The list representation does not have a span component. This is
* because list Tcl_Obj's with spans are always created from existing lists
* and never from strings (see SetListFromAny) and thus their string
diff --git a/generic/tclListObj.c b/generic/tclListObj.c
index 143c476..1d5f7f1 100644
--- a/generic/tclListObj.c
+++ b/generic/tclListObj.c
@@ -3470,16 +3470,21 @@ UpdateStringOfList(
* Mark the list as being canonical; although it will now have a string
* rep, it is one we derived through proper "canonical" quoting and so
* it's known to be free from nasties relating to [concat] and [eval].
- * However, we only do this if this is not a spanned list. Marking the
- * storage canonical for a spanned list make ALL lists using the storage
- * canonical which is not right. (Consider a list generated from a
+ * However, we only do this if
+ *
+ * (a) the store is not shared as a shared store may be referenced by
+ * multiple lists with different string reps. (see [a366c6efee]), AND
+ *
+ * (b) list does not have a span. Consider a list generated from a
* string and then this function called for a spanned list generated
- * from it). On the other hand, a spanned list is always canonical
+ * from the original list. We cannot mark the list store as canonical as
+ * that would also make the originating list canonical, which it may not
+ * be. On the other hand, the spanned list itself is always canonical
* (never generated from a string) so it does not have to be explicitly
* marked as such. The ListObjIsCanonical macro takes this into account.
* See the comments there.
*/
- if (listRep.spanPtr == NULL) {
+ if (listRep.storePtr->refCount < 2 && listRep.spanPtr == NULL) {
LIST_ASSERT(listRep.storePtr->firstUsed == 0);/* Invariant */
listRep.storePtr->flags |= LISTSTORE_CANONICAL;
}
diff --git a/tests/lreplace.test b/tests/lreplace.test
index 009170e..55b3ee3 100644
--- a/tests/lreplace.test
+++ b/tests/lreplace.test
@@ -505,6 +505,15 @@ test ledit-5.2 {compiled lreplace: Bug 47ac84309b} {
}} {a b c}
} {a b A c}
+test ledit-bug-a366c6efee {Bug [a366c6efee]} -body {
+ apply {{} {
+ set l { }
+ string length [ledit l 1 1]; # Force string generation
+ set result foo
+ append result " " bar
+ }}
+} -result "foo bar"
+
# Testing for compiled behaviour. Far too many variations to check with
# spelt-out tests. Note that this *just* checks whether the compiled version
# and the interpreted version are the same, not whether the interpreted