gitk: use -profile tcl8 on encoding conversions

gitk in the prior commit learned to apply -profile tcl8 to all input data streams, avoiding errors on non-binary data streams whose encoding is not utf-8. But, gitk also consumes binary data streams (generally blobs from commits), and internally decodes this to support various displays. With Tcl9, errors occur in this decoding for the same reasons described in the previous commit: basically, the underlying data was not validated to conform to the given encoding, and this source encoding may not be utf-8. gitk performs this decoding using Tcl's '[encoding convert from' operator. For example, the 7th commit in gitk's history has the extended ascii value 0xA9, so gitk 9a40c50c1e in gitk's repository raises an exception. The error log has: unexpected byte sequence starting at index 11: '\xA9' while executing "encoding convertfrom $diffencoding $line" (procedure "parseblobdiffline" line 135) invoked from within "parseblobdiffline $ids $line" (procedure "getblobdiffline" line 16) invoked from within "getblobdiffline file6 9a40c50c1e05c0658b7a7c68b56d615eb6f170dd" ("eval" body line 1) invoked from within "eval $script" (procedure "dorunq" line 11) invoked from within "dorunq" ("after" script) This problem has a similar fix to the prior issue: we must use the tlc8 profile when converting this data. Do so, again only on Tcl9 as Tcl8.6 does not recognize -profile, and only Tcl 9.0 makes strict the default. Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>

Mark Levedahl committed May 18, 2025 at 10:41 UTC ac222bc02df9aef49d4a6ee839762c2902961a21
1 file changed +19 -12
gitk
+19 -12
@@ -44,6 +44,13 @@ if {[package vcompare $::tcl_version 9.0] >= 0} {
44 chan configure $f -profile tcl8
45 return $f
46 }
47 + proc convertfrom args {
48 + return [encoding convertfrom -profile tcl8 {*}$args]
49 + }
50 +} else {
51 + proc convertfrom args {
52 + return [encoding convertfrom {*}$args]
53 + }
54 }
55
56 ######################################################################
@@ -7823,7 +7830,7 @@ proc gettreeline {gtf id} {
7830 if {[string index $fname 0] eq "\""} {
7831 set fname [lindex $fname 0]
7832 }
7826 - set fname [encoding convertfrom utf-8 $fname]
7833 + set fname [convertfrom utf-8 $fname]
7834 lappend treefilelist($id) $fname
7835 }
7836 if {![eof $gtf]} {
@@ -8083,7 +8090,7 @@ proc gettreediffline {gdtf ids} {
8090 if {[string index $file 0] eq "\""} {
8091 set file [lindex $file 0]
8092 }
8086 - set file [encoding convertfrom utf-8 $file]
8093 + set file [convertfrom utf-8 $file]
8094 if {$file ne [lindex $treediff end]} {
8095 lappend treediff $file
8096 lappend sublist $file
@@ -8219,7 +8226,7 @@ proc makediffhdr {fname ids} {
8226 global ctext curdiffstart treediffs diffencoding
8227 global ctext_file_names jump_to_here targetline diffline
8228
8222 - set fname [encoding convertfrom utf-8 $fname]
8229 + set fname [convertfrom utf-8 $fname]
8230 set diffencoding [get_path_encoding $fname]
8231 set i [lsearch -exact $treediffs($ids) $fname]
8232 if {$i >= 0} {
@@ -8281,7 +8288,7 @@ proc parseblobdiffline {ids line} {
8288
8289 if {![string compare -length 5 "diff " $line]} {
8290 if {![regexp {^diff (--cc|--git) } $line m type]} {
8284 - set line [encoding convertfrom utf-8 $line]
8291 + set line [convertfrom utf-8 $line]
8292 $ctext insert end "$line\n" hunksep
8293 continue
8294 }
@@ -8330,7 +8337,7 @@ proc parseblobdiffline {ids line} {
8337 makediffhdr $fname $ids
8338
8339 } elseif {![string compare -length 16 "* Unmerged path " $line]} {
8333 - set fname [encoding convertfrom utf-8 [string range $line 16 end]]
8340 + set fname [convertfrom utf-8 [string range $line 16 end]]
8341 $ctext insert end "\n"
8342 set curdiffstart [$ctext index "end - 1c"]
8343 lappend ctext_file_names $fname
@@ -8343,7 +8350,7 @@ proc parseblobdiffline {ids line} {
8350
8351 } elseif {![string compare -length 2 "@@" $line]} {
8352 regexp {^@@+} $line ats
8346 - set line [encoding convertfrom $diffencoding $line]
8353 + set line [convertfrom $diffencoding $line]
8354 $ctext insert end "$line\n" hunksep
8355 if {[regexp { \+(\d+),\d+ @@} $line m nl]} {
8356 set diffline $nl
@@ -8372,10 +8379,10 @@ proc parseblobdiffline {ids line} {
8379 $ctext insert end "$line\n" filesep
8380 }
8381 } elseif {$currdiffsubmod != "" && ![string compare -length 3 " >" $line]} {
8375 - set line [encoding convertfrom $diffencoding $line]
8382 + set line [convertfrom $diffencoding $line]
8383 $ctext insert end "$line\n" dresult
8384 } elseif {$currdiffsubmod != "" && ![string compare -length 3 " <" $line]} {
8378 - set line [encoding convertfrom $diffencoding $line]
8385 + set line [convertfrom $diffencoding $line]
8386 $ctext insert end "$line\n" d0
8387 } elseif {$diffinhdr} {
8388 if {![string compare -length 12 "rename from " $line]} {
@@ -8383,7 +8390,7 @@ proc parseblobdiffline {ids line} {
8390 if {[string index $fname 0] eq "\""} {
8391 set fname [lindex $fname 0]
8392 }
8386 - set fname [encoding convertfrom utf-8 $fname]
8393 + set fname [convertfrom utf-8 $fname]
8394 set i [lsearch -exact $treediffs($ids) $fname]
8395 if {$i >= 0} {
8396 setinlist difffilestart $i $curdiffstart
@@ -8402,12 +8409,12 @@ proc parseblobdiffline {ids line} {
8409 set diffinhdr 0
8410 return
8411 }
8405 - set line [encoding convertfrom utf-8 $line]
8412 + set line [convertfrom utf-8 $line]
8413 $ctext insert end "$line\n" filesep
8414
8415 } else {
8416 set line [string map {\x1A ^Z} \
8410 - [encoding convertfrom $diffencoding $line]]
8417 + [convertfrom $diffencoding $line]]
8418 # parse the prefix - one ' ', '-' or '+' for each parent
8419 set prefix [string range $line 0 [expr {$diffnparents - 1}]]
8420 set tag [expr {$diffnparents > 1? "m": "d"}]
@@ -12279,7 +12286,7 @@ proc cache_gitattr {attr pathlist} {
12286 foreach row [split $rlist "\n"] {
12287 if {[regexp "(.*): $attr: (.*)" $row m path value]} {
12288 if {[string index $path 0] eq "\""} {
12282 - set path [encoding convertfrom utf-8 [lindex $path 0]]
12289 + set path [convertfrom utf-8 [lindex $path 0]]
12290 }
12291 set path_attr_cache($attr,$path) $value
12292 }