From 0da766e50540fbb92b2cb510dab13eee054b097c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 12 Feb 2021 10:03:01 +0100 Subject: [PATCH] =?UTF-8?q?selection:=20don=E2=80=99t=20strip=20formatting?= =?UTF-8?q?=20C0=20control=20characters=20in=20bracketed=20paste=20mode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It’s ok to let the receiving end handle formatting C0 control characters in bracketed paste mode. In fact, we *must* let them through. Otherwise it is impossible to paste e.g. tabs into editors and similar applications. --- CHANGELOG.md | 1 + selection.c | 43 +++++++++++++++++++++++++------------------ 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d43d6f1f..8d8dc9de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -88,6 +88,7 @@ `shift` to be pressed while used in a mouse grabbing application. This meant the mouse event was never seen by the application. +* `BS`, `HT` and `DEL` from being stripped in bracketed paste mode. ### Security diff --git a/selection.c b/selection.c index cb625541..f5a114c8 100644 --- a/selection.c +++ b/selection.c @@ -1615,6 +1615,15 @@ fdm_receive(struct fdm *fdm, int fd, int events, void *data) */ char *p = text; size_t left = count; + +#define skip_one() \ + do { \ + ctx->decoder(ctx, p, i); \ + xassert(i + 1 <= left); \ + p += i + 1; \ + left -= i + 1; \ + } while (0) + again: for (size_t i = 0; i < left; i++) { switch (p[i]) { @@ -1629,33 +1638,29 @@ fdm_receive(struct fdm *fdm, int fd, int events, void *data) case '\r': /* Convert \r\n -> \r */ if (!ctx->bracketed && i + 1 < left && p[i + 1] == '\n') { - ctx->decoder(ctx, p, i + 1); - - xassert(i + 2 <= left); - p += i + 2; - left -= i + 2; + i++; + skip_one(); goto again; } break; /* C0 non-formatting control characters (\b \t \n \r excluded) */ case '\x01': case '\x02': case '\x03': case '\x04': case '\x05': - case '\x06': case '\x07': case '\x0b': case '\x0c': case '\x0e': - case '\x0f': case '\x10': case '\x11': case '\x12': case '\x13': - case '\x14': case '\x15': case '\x16': case '\x17': case '\x18': - case '\x19': case '\x1a': case '\x1b': case '\x1c': case '\x1d': - case '\x1e': case '\x1f': - /* FALLTHROUGH */ + case '\x06': case '\x07': case '\x0e': case '\x0f': case '\x10': + case '\x11': case '\x12': case '\x13': case '\x14': case '\x15': + case '\x16': case '\x17': case '\x18': case '\x19': case '\x1a': + case '\x1b': case '\x1c': case '\x1d': case '\x1e': case '\x1f': + skip_one(); + goto again; /* Additional control characters stripped by default (but * configurable) in XTerm: BS, HT, DEL */ - case '\b': case '\t': case '\x7f': - ctx->decoder(ctx, p, i); - - xassert(i + 1 <= left); - p += i + 1; - left -= i + 1; - goto again; + case '\b': case '\t': case '\v': case '\f': case '\x7f': + if (!ctx->bracketed) { + skip_one(); + goto again; + } + break; } } @@ -1663,6 +1668,8 @@ fdm_receive(struct fdm *fdm, int fd, int events, void *data) left = 0; } +#undef skip_one + done: ctx->finish(ctx); clipboard_receive_done(fdm, ctx);