Tcl Source Code

View Ticket
Login
Ticket UUID: 526b01c0b9921b90618f82c398dc2684a60a053a
Title: lset with 2+ indices on an unshared lseq list is a use-after-free (crash)
Type: Bug Created on: 2026-10-18 09:48:35
Submitter: rocketship98 Assigned to: nobody
Subsystem: 14. List Object Severity: Severe
Priority: 7 High Last modified: 2026-10-18 11:03:01
Status: Open Closed by: nobody
Resolution: None Closed on:
Version: 9.0.5, 9.1.0
Description:
set l [lseq 5]
lset l 1 0 X
for {set i 0} {$i < 2000} {incr i} {lappend z [list $i]}

On an -O2 build the loop segfaults (TclThreadAllocObj, object pool corrupted). On a --enable-symbols=mem build it panics at once: Tcl_DbIncrRefCount: Tcl_Obj allocated in another thread, from TclListObjSetElement (tclListObj.c:3289) called by TclLsetFlat (tclListObj.c:3108).

Same with lset l {1 0} X, with lreverse [lseq 5] and lrange [lseq 10] 2 6 as the list, and after a lindex $l 1 has run on the lseq list. Not affected: single-index lset, native lists, lrepeat.

Cause: in TclLsetFlat, elemPtrs comes from Tcl_ListObjGetElements on the arithseries list, i.e. its cached element array, with no reference added. subListObj = elemPtrs[index] is then passed to TclListObjSetElement(parentList, index, subListObj). That call converts the abstract list to a native list (SetListFromAny, building new elements through indexProc) and frees the arithseries internal rep, including the cache, so subListObj (refCount 1, owned only by the cache) is freed before it is stored. A fix could be to take a reference on subListObj around the conversion, or to convert parentList to a native list before reading elemPtrs.

Found by mutation testing of the abstract-list code (using claude, so can't say i understand his reasoning). But it crashes my windows wish91.exe

User Comments:
serhiy.storchaka added on 2026-10-18 10:19:50:

Confirmed on trunk and 9.0.5, and the analysis is right. Proposed fix in branch lset-abstract-list-uaf: TclLsetFlat() holds a reference to the sublist while storing it, the first option suggested here. Tests lset-19.1 and 19.2.


juliannoble2 added on 2026-10-18 11:03:01:
Verified on one of APN's tclsfe9.1 builds and my own Tcl 9.0 builds (using non-standard zig build system)

Can crash even without the for loop in an interactive tclsh

    set l [lseq 5]
    lset l 1 0 X

or sometimes repeat the lset command.