Skip to content

Commit 38d334f

Browse files
committed
Fix [54329e39c7]
1 parent 531cd74 commit 38d334f

File tree

2 files changed

+47
-6
lines changed

2 files changed

+47
-6
lines changed

generic/tclExecute.c

+26-6
Original file line numberDiff line numberDiff line change
@@ -6789,8 +6789,8 @@ TEBCresume(
67896789
goto gotError;
67906790
}
67916791
if (Tcl_IsShared(listPtr)) {
6792-
objPtr = TclDuplicatePureObj(
6793-
interp, listPtr, &tclListType);
6792+
/* Do NOT use TclDuplicatePureObj here - shimmers abstract list to list */
6793+
objPtr = Tcl_DuplicateObj(listPtr);
67946794
if (!objPtr) {
67956795
goto gotError;
67966796
}
@@ -6867,21 +6867,41 @@ TEBCresume(
68676867
for (i = 0; i < numLists; i++) {
68686868
varListPtr = infoPtr->varLists[i];
68696869
numVars = varListPtr->numVars;
6870+
int hasAbstractList;
68706871

68716872
listPtr = OBJ_AT_DEPTH(listTmpDepth);
6872-
status = TclListObjGetElementsM(
6873-
interp, listPtr, &listLen, &elements);
6873+
hasAbstractList =
6874+
TclHasInternalRep(listPtr, &tclArithSeriesType);
6875+
DECACHE_STACK_INFO();
6876+
if (hasAbstractList) {
6877+
status = Tcl_ListObjLength(interp, listPtr, &listLen);
6878+
elements = NULL;
6879+
} else {
6880+
status = TclListObjGetElementsM(
6881+
interp, listPtr, &listLen, &elements);
6882+
}
68746883
if (status != TCL_OK) {
6884+
CACHE_STACK_INFO();
68756885
goto gotError;
68766886
}
6877-
6887+
CACHE_STACK_INFO();
68786888

68796889
valIndex = (iterNum * numVars);
68806890
for (j = 0; j < numVars; j++) {
68816891
if (valIndex >= listLen) {
68826892
TclNewObj(valuePtr);
68836893
} else {
6884-
valuePtr = elements[valIndex];
6894+
if (elements) {
6895+
valuePtr = elements[valIndex];
6896+
} else {
6897+
DECACHE_STACK_INFO();
6898+
valuePtr = TclArithSeriesObjIndex(
6899+
NULL, listPtr, valIndex);
6900+
if (valuePtr == NULL) {
6901+
TclNewObj(valuePtr);
6902+
}
6903+
CACHE_STACK_INFO();
6904+
}
68856905
}
68866906

68876907
varIndex = varListPtr->varIndexes[j];

tests/lseq.test

+21
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,16 @@ testConstraint arithSeriesShimmerOk 1
2020
#testConstraint has64BitLengths [expr {$tcl_platform(pointerSize) == 8}]
2121
#testConstraint has32BitLengths [expr {$tcl_platform(pointerSize) == 4}]
2222

23+
proc memusage {} {
24+
set fd [open /proc/[pid]/statm]
25+
set line [gets $fd]
26+
if {[llength $line] != 7} {
27+
error "Unexpected /proc/pid/statm format"
28+
}
29+
return [lindex $line 5]
30+
}
31+
testConstraint hasMemUsage [expr {![catch {memusage}]}]
32+
2333
# Arg errors
2434
test lseq-1.1 {error cases} -body {
2535
lseq
@@ -671,6 +681,17 @@ test lseq-convertToList {does not result in a memory error} -body {
671681
list [catch {set var1 [lindex [lreplace [lseq 1 2] 1 1 hello] 0]} cres] $cres
672682
} -cleanup {unset var1 cres} -result {1 {can't set "var1": this is an error}}
673683

684+
test lseq-bug-54329e39c7 {does not cause memory bloat} -constraints {
685+
hasMemUsage
686+
} -body {
687+
set l [lseq 1000000]
688+
proc p l {foreach x $l {}}
689+
set premem [memusage]
690+
p $l
691+
set postmem [memusage]
692+
expr {($postmem - $premem) < 10}
693+
} -result 1
694+
674695
# cleanup
675696
::tcltest::cleanupTests
676697

0 commit comments

Comments
 (0)