fix(terminal): prevent UTF-8 chunk truncation falling back to GBK

This fixes an issue where outputting large amounts of Chinese text caused the 4096-byte chunk to split a multi-byte UTF-8 character, falsely triggering the GBK fallback logic and resulting in garbled text.
This commit is contained in:
duorameng
2026-06-18 17:51:54 +08:00
parent 50daa79c0a
commit 19374e7054
+60 -8
View File
@@ -138,16 +138,42 @@ func (tc *TerminalController) handlePtyMode(conn *websocket.Conn, userID string)
go func() { go func() {
defer wg.Done() defer wg.Done()
buf := make([]byte, 4096) buf := make([]byte, 4096)
var remainder []byte
for { for {
n, err := ptmx.Read(buf) n, err := ptmx.Read(buf)
if err != nil {
return
}
if n > 0 { if n > 0 {
text := toUTF8(buf[:n]) chunk := append(remainder, buf[:n]...)
lastSafe := len(chunk)
for i := len(chunk); i > 0 && i > len(chunk)-4; i-- {
if utf8.RuneStart(chunk[i-1]) {
if !utf8.FullRune(chunk[i-1 : len(chunk)]) {
lastSafe = i - 1
}
break
}
}
safe := chunk[:lastSafe]
if len(safe) == 0 && len(chunk) >= 4 {
safe = chunk
remainder = nil
} else {
remainder = make([]byte, len(chunk[lastSafe:]))
copy(remainder, chunk[lastSafe:])
}
if len(safe) > 0 {
text := toUTF8(safe)
writeMessage([]byte(text)) writeMessage([]byte(text))
} }
} }
if err != nil {
if len(remainder) > 0 {
writeMessage([]byte(toUTF8(remainder)))
}
return
}
}
}() }()
// 启动 ping 协程 // 启动 ping 协程
@@ -259,16 +285,42 @@ func (tc *TerminalController) handlePipeMode(conn *websocket.Conn, userID string
defer wg.Done() defer wg.Done()
defer func() { recover() }() defer func() { recover() }()
buf := make([]byte, 4096) buf := make([]byte, 4096)
var remainder []byte
for { for {
n, err := reader.Read(buf) n, err := reader.Read(buf)
if err != nil {
return
}
if n > 0 { if n > 0 {
text := toUTF8(buf[:n]) chunk := append(remainder, buf[:n]...)
lastSafe := len(chunk)
for i := len(chunk); i > 0 && i > len(chunk)-4; i-- {
if utf8.RuneStart(chunk[i-1]) {
if !utf8.FullRune(chunk[i-1 : len(chunk)]) {
lastSafe = i - 1
}
break
}
}
safe := chunk[:lastSafe]
if len(safe) == 0 && len(chunk) >= 4 {
safe = chunk
remainder = nil
} else {
remainder = make([]byte, len(chunk[lastSafe:]))
copy(remainder, chunk[lastSafe:])
}
if len(safe) > 0 {
text := toUTF8(safe)
writeMessage([]byte(text)) writeMessage([]byte(text))
} }
} }
if err != nil {
if len(remainder) > 0 {
writeMessage([]byte(toUTF8(remainder)))
}
return
}
}
} }
wg.Add(2) wg.Add(2)