Tcl Source Code

View Ticket
Bounty program for improvements to Tcl and certain Tcl packages.
15:56 Ticket [e87bcf819f] array for fails to detect array change made through upvar status still Open with 3 other changes artifact: 5c8f767629 user: dkf
15:19 Ticket [e87bcf819f]: 3 changes artifact: d6c5384582 user: dkf
15:11 Ticket [e87bcf819f]: 4 changes artifact: 0b62fb06fe user: dkf
15:06 Ticket [e87bcf819f]: 4 changes artifact: cd965326b6 user: dkf
11:56 Ticket [e87bcf819f]: 3 changes artifact: 6f591e569c user: dgp
23:11 Ticket [e87bcf819f]: 4 changes artifact: e1675ea83d user: dgp
Candidate fix for [e87bcf819f]. Makes sure the unset of a scalar variable linked to an array element... check-in: 701d26870f user: dgp tags: bug-e87bcf819f
19:13 Ticket [e87bcf819f] array for fails to detect array change made through upvar status still Open with 3 other changes artifact: da4ded8276 user: dgp
19:13 Ticket [e87bcf819f]: 3 changes artifact: 81b9d0dc8c user: dgp
19:10 New ticket [e87bcf819f]. artifact: abebe37771 user: dgp

Ticket UUID: e87bcf819f03cea4e35dca24cac7228766f53b0
Title: [array for] fails to detect array change made through upvar
Type: Bug Version:
Submitter: dgp Created on: 2018-04-22 19:10:03
Subsystem: 07. Variables Assigned To: dkf
Priority: 5 Medium Severity: Important
Status: Open Last Modified: 2018-05-07 15:56:29
Resolution: None Closed By: nobody
    Closed on:
Contrast these two:

% proc demo {} {
array set a {m 1 n 2 o 3 p 4}
try {                                 
    array for {k v} a {unset a(n)}
} on error {m} {
    puts "ERROR: $m"
} finally {
    puts [array get a]
% demo
ERROR: array changed during iteration
p 4 m 1 o 3

% proc demo {} {
array set a {m 1 n 2 o 3 p 4}
upvar 0 a(n) l
try {
    array for {k v} a {catch {unset l}}
} on error {m} {
    puts "ERROR:$m"
} finally {
    puts [array get a]
% demo
p 4 m 1 o 3
User Comments: dkf added on 2018-05-07 15:56:29:

And the bug is that the unset isn't killing the searches, and that's because the variable link is meaning that we're arriving at the element (which knows that it is in a TclVarHashTable) without going back to check if this makes things become invalidated. Which it can't do because we don't currently keep a pointer to the containing variable in the TclVarHashTable (the pointer could be NULL for non-array use cases, I guess). I don't know what the consequences of keeping such a pointer would be, apart from a small amount of extra memory usage.

The first option is correct; an error should be thrown by array for on internal modification.

dkf added on 2018-05-07 15:19:26:

The changes to tclOOBasic.c look OK to me. They won't interfere with TIP 500.

dkf added on 2018-05-07 15:11:01:

Xref: bug-e87bcf819f

dkf added on 2018-05-07 15:06:16:

What I find interesting is that the [unset l] doesn't change the structure of the array. It's because there's still a reference to it (from the l variable) but it's still unexpected to anyone who isn't experienced with Tcl's guts.

dgp added on 2018-04-30 11:56:54:
Note that the machinery created here might be useful
in fixing the very old bug/RFE

as well.

dgp added on 2018-04-22 23:11:51:
Candidate fix on branch bug-e87bcf819f.

dkf should comment on the changes made to TclOOBasic.c

dgp added on 2018-04-22 19:13:46:
The same failure probably exists in the [array startsearch], etc commands.

dgp added on 2018-04-22 19:13:11:
Because this evades the protection against using
a Tcl_HashSearch after the hash table has changed,
it is likely this can be used to create segfaults.