Tcl Source Code

View Ticket
Login
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:
Description:
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: (text/html)
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.
<p>
The first option is correct; an error <i>should</i> be thrown by <tt>array for</tt> on internal modification.

dkf added on 2018-05-07 15:19:26: (text/html)
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: (text/html)
<tt>Xref: <a href="/tcl/timeline?r=bug-e87bcf819f">bug-e87bcf819f</a></tt>

dkf added on 2018-05-07 15:06:16: (text/html)
What I find interesting is that the [<tt>unset l</tt>] doesn't change the structure of the array. It's because there's still a reference to it (from the <tt>l</tt> 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

https://core.tcl-lang.org/tcl/tktview?name=572889

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.