Modern terminals and applications emit OSC (Operating System Command),
DCS, SOS, PM, and APC escape sequences (e.g. for setting window
titles).  The text console currently does not recognise these
string-type introducers, so each byte of the payload is interpreted as
a normal character or a new escape, producing garbage on screen.

Add a TTY_STATE_OSC state that silently consumes all bytes until the
sequence is terminated by BEL or ST (ESC \).

Signed-off-by: Marc-André Lureau <[email protected]>
---
 ui/console-vc.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/ui/console-vc.c b/ui/console-vc.c
index 7bbd65dea27..5eca9a5c004 100644
--- a/ui/console-vc.c
+++ b/ui/console-vc.c
@@ -45,6 +45,7 @@ enum TTYState {
     TTY_STATE_CSI,
     TTY_STATE_G0,
     TTY_STATE_G1,
+    TTY_STATE_OSC,
 };
 
 typedef struct QemuTextConsole {
@@ -869,6 +870,10 @@ static void vc_putchar(VCChardev *vc, int ch)
             vc->state = TTY_STATE_G0;
         } else if (ch == ')') {
             vc->state = TTY_STATE_G1;
+        } else if (ch == ']' || ch == 'P' || ch == 'X'
+                   || ch == '^' || ch == '_') {
+            /* String sequences: OSC, DCS, SOS, PM, APC */
+            vc->state = TTY_STATE_OSC;
         } else if (ch == '7') {
             vc_save_cursor(vc);
             vc->state = TTY_STATE_NORM;
@@ -1027,6 +1032,16 @@ static void vc_putchar(VCChardev *vc, int ch)
             break;
         }
         break;
+    case TTY_STATE_OSC: /* Operating System Command: ESC ] ... BEL/ST */
+        if (ch == '\a') {
+            /* BEL terminates OSC */
+            vc->state = TTY_STATE_NORM;
+        } else if (ch == 27) {
+            /* ESC might start ST (ESC \) */
+            vc->state = TTY_STATE_ESC;
+        }
+        /* All other bytes are silently consumed */
+        break;
     case TTY_STATE_G0: /* set character sets */
     case TTY_STATE_G1: /* set character sets */
         switch (ch) {

-- 
2.53.0


Reply via email to