Skip to content

Commit 044cff5

Browse files
committed
fix mask loading
1 parent d286a7a commit 044cff5

1 file changed

Lines changed: 25 additions & 13 deletions

File tree

tcl/windows/tree.tcl

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,42 +1078,53 @@ proc ::tree::mask::safeReadMaskFile {filename} {
10781078

10791079
# Read file contents
10801080
if {[catch {
1081-
set fd [open $filename r]
1081+
set fd [::open $filename r]
10821082
fconfigure $fd -encoding utf-8
10831083
set content [read $fd]
1084-
close $fd
1084+
::close $fd
10851085
} err]} {
10861086
return 0
10871087
}
10881088

10891089
# Trim whitespace
10901090
set content [string trim $content]
10911091

1092-
# Validate file format: must be exactly "set ::tree::mask::maskSerialized {...}"
1093-
# The content inside braces must be a valid Tcl list (key-value pairs)
1094-
if {![regexp {^set\s+::tree::mask::maskSerialized\s+(\{.*\})\s*$} $content -> listData]} {
1092+
# Validate file format: must start with "set ::tree::mask::maskSerialized"
1093+
set prefix "set ::tree::mask::maskSerialized "
1094+
if {![string equal -length [string length $prefix] $content $prefix]} {
10951095
return 0
10961096
}
10971097

1098+
# Extract everything after the prefix - this handles multi-line content
1099+
set listData [string range $content [string length $prefix] end]
1100+
set listData [string trim $listData]
1101+
10981102
# Validate that the list data is well-formed by attempting to parse it
10991103
# as a Tcl list. This ensures balanced braces and valid list structure.
1104+
# Tcl's llength handles multi-line brace-delimited content correctly.
11001105
if {[catch {llength $listData}]} {
11011106
return 0
11021107
}
11031108

1104-
# Additional validation: check that all keys look like valid FEN strings
1105-
# and all values are proper lists. We parse the data safely.
1109+
# The save function uses [list [array get ...]] which wraps data in braces,
1110+
# so llength returns 1. We need to extract the inner data for validation.
1111+
if {[catch {set innerData [lindex $listData 0]}]} {
1112+
return 0
1113+
}
1114+
1115+
# Validate the inner data structure
1116+
# Check a sample of entries for performance (first 100 pairs)
11061117
if {[catch {
1107-
set parsedList $listData
1108-
set len [llength $parsedList]
1118+
set len [llength $innerData]
11091119
# Must have even number of elements (key-value pairs)
11101120
if {$len % 2 != 0} {
11111121
error "Invalid mask data structure"
11121122
}
1113-
# Validate each key-value pair
1114-
for {set i 0} {$i < $len} {incr i 2} {
1115-
set key [lindex $parsedList $i]
1116-
set value [lindex $parsedList [expr {$i + 1}]]
1123+
# Validate a sample of key-value pairs (up to 100)
1124+
set maxCheck [expr {min($len, 200)}]
1125+
for {set i 0} {$i < $maxCheck} {incr i 2} {
1126+
set key [lindex $innerData $i]
1127+
set value [lindex $innerData [expr {$i + 1}]]
11171128
# Key should be a non-empty string (FEN position identifier)
11181129
if {$key eq ""} {
11191130
error "Empty key in mask data"
@@ -1128,6 +1139,7 @@ proc ::tree::mask::safeReadMaskFile {filename} {
11281139
}
11291140

11301141
# All validations passed, set the data
1142+
# Keep the original listData format (with outer braces) for compatibility
11311143
set ::tree::mask::maskSerialized $listData
11321144
return 1
11331145
}

0 commit comments

Comments
 (0)