Trim unsupported OSC sequences (#4169)

Fix #4169
This commit is contained in:
Junegunn Choi 2025-01-10 20:53:47 +09:00
parent d7b13f3408
commit bd3e65df4d
No known key found for this signature in database
GPG Key ID: 254BC280FEF9C627
2 changed files with 28 additions and 12 deletions

View File

@ -98,11 +98,11 @@ func isPrint(c uint8) bool {
return '\x20' <= c && c <= '\x7e' return '\x20' <= c && c <= '\x7e'
} }
func matchOperatingSystemCommand(s string) int { func matchOperatingSystemCommand(s string, start int) int {
// `\x1b][0-9][;:][[:print:]]+(?:\x1b\\\\|\x07)` // `\x1b][0-9][;:][[:print:]]+(?:\x1b\\\\|\x07)`
// ^ match starting here // ^ match starting here after the first printable character
// //
i := 5 // prefix matched in nextAnsiEscapeSequence() i := start // prefix matched in nextAnsiEscapeSequence()
for ; i < len(s) && isPrint(s[i]); i++ { for ; i < len(s) && isPrint(s[i]); i++ {
} }
if i < len(s) { if i < len(s) {
@ -156,7 +156,7 @@ func isCtrlSeqStart(c uint8) bool {
// nextAnsiEscapeSequence returns the ANSI escape sequence and is equivalent to // nextAnsiEscapeSequence returns the ANSI escape sequence and is equivalent to
// calling FindStringIndex() on the below regex (which was originally used): // calling FindStringIndex() on the below regex (which was originally used):
// //
// "(?:\x1b[\\[()][0-9;:?]*[a-zA-Z@]|\x1b][0-9][;:][[:print:]]+(?:\x1b\\\\|\x07)|\x1b.|[\x0e\x0f]|.\x08)" // "(?:\x1b[\\[()][0-9;:?]*[a-zA-Z@]|\x1b][0-9]+[;:][[:print:]]+(?:\x1b\\\\|\x07)|\x1b.|[\x0e\x0f]|.\x08)"
func nextAnsiEscapeSequence(s string) (int, int) { func nextAnsiEscapeSequence(s string) (int, int) {
// fast check for ANSI escape sequences // fast check for ANSI escape sequences
i := 0 i := 0
@ -191,12 +191,20 @@ Loop:
} }
} }
// match: `\x1b][0-9][;:][[:print:]]+(?:\x1b\\\\|\x07)` // match: `\x1b][0-9]+[;:][[:print:]]+(?:\x1b\\\\|\x07)`
if i+5 < len(s) && s[i+1] == ']' && isNumeric(s[i+2]) && if i+5 < len(s) && s[i+1] == ']' {
(s[i+3] == ';' || s[i+3] == ':') && isPrint(s[i+4]) { j := 2
// \x1b][0-9]+[;:][[:print:]]+(?:\x1b\\\\|\x07)
// ------
for ; i+j < len(s) && isNumeric(s[i+j]); j++ {
}
if j := matchOperatingSystemCommand(s[i:]); j != -1 { // \x1b][0-9]+[;:][[:print:]]+(?:\x1b\\\\|\x07)
return i, i + j // ---------------
if j > 2 && i+j+1 < len(s) && (s[i+j] == ';' || s[i+j] == ':') && isPrint(s[i+j+1]) {
if k := matchOperatingSystemCommand(s[i:], j+2); k != -1 {
return i, i + k
}
} }
} }

View File

@ -337,17 +337,25 @@ func TestExtractColor(t *testing.T) {
}) })
state = nil state = nil
var color24 tui.Color = (1 << 24) + (180 << 16) + (190 << 8) + 254
src = "\x1b[1mhello \x1b[22;1;38:2:180:190:254mworld" src = "\x1b[1mhello \x1b[22;1;38:2:180:190:254mworld"
check(func(offsets *[]ansiOffset, state *ansiState) { check(func(offsets *[]ansiOffset, state *ansiState) {
if len(*offsets) != 2 { if len(*offsets) != 2 {
t.Fail() t.Fail()
} }
var color tui.Color = (1 << 24) + (180 << 16) + (190 << 8) + 254 if state.fg != color24 || state.attr != 1 {
if state.fg != color || state.attr != 1 {
t.Fail() t.Fail()
} }
assert((*offsets)[0], 0, 6, -1, -1, true) assert((*offsets)[0], 0, 6, -1, -1, true)
assert((*offsets)[1], 6, 11, color, -1, true) assert((*offsets)[1], 6, 11, color24, -1, true)
})
src = "\x1b]133;A\x1b\\hello \x1b]133;C\x1b\\world"
check(func(offsets *[]ansiOffset, state *ansiState) {
if len(*offsets) != 1 {
t.Fail()
}
assert((*offsets)[0], 0, 11, color24, -1, true)
}) })
} }