From 28db7d06dc30de2f4121bf6e47668ca4493accfc Mon Sep 17 00:00:00 2001 From: Matthias Diester Date: Sat, 4 Jan 2025 23:02:43 +0100 Subject: [PATCH] Fix operating system command sequence panic Ref: https://github.com/homeport/termshot/issues/220 Ref: https://github.com/homeport/termshot/issues/102 Change skip logic to support both BEL and ST as terminator. --- parse.go | 15 +++++++++++---- parse_test.go | 12 ++++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/parse.go b/parse.go index 69b873c..f8fcbd6 100644 --- a/parse.go +++ b/parse.go @@ -31,6 +31,11 @@ import ( "strings" ) +const ( + bel = '\a' // bel (Bell) + st = '\\' // st (String Terminator) +) + var ( escapeSeqRegExp = regexp.MustCompile(`\x1b\[(\d+(;\d+)*)m`) boldMarker = regexp.MustCompile(`\*([^*]+?)\*`) @@ -93,15 +98,17 @@ func ParseStream(in io.Reader, opts ...ParseOption) (*String, error) { panic("failed to parse ANSI sequence") } - var skipUntil = func(end rune) { + var skipUntil = func(ends ...rune) { for { r, _, err := input.ReadRune() if err == io.EOF { panic("reached end of file before reaching end identifier") } - if r == end { - return + for _, end := range ends { + if r == end { + return + } } } } @@ -169,7 +176,7 @@ func ParseStream(in io.Reader, opts ...ParseOption) (*String, error) { } case ']': - skipUntil('\a') + skipUntil(bel, st) } } diff --git a/parse_test.go b/parse_test.go index 0ba8e55..3997489 100644 --- a/parse_test.go +++ b/parse_test.go @@ -54,6 +54,18 @@ var _ = Describe("parse input string", func() { Expect(err).ToNot(HaveOccurred()) Expect(result.String()).To(Equal("Hello, \x1b[1mWorld\x1b[0m!")) }) + + It("should process Operating System Command sequences that terminate on bell", func() { + result, err := ParseStream(strings.NewReader("\x1b]2;title\a")) + Expect(err).ToNot(HaveOccurred()) + Expect(result).ToNot(BeNil()) + }) + + It("should process Operating System Command sequences that terminate string terminator", func() { + result, err := ParseStream(strings.NewReader("\x1b]7;file://host/home/foobar/dir\x1b\\")) + Expect(err).ToNot(HaveOccurred()) + Expect(result).ToNot(BeNil()) + }) }) Context("parse Select Graphic Rendition (SGR) based input", func() {