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);