selection: don’t strip formatting C0 control characters in bracketed paste mode

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.
This commit is contained in:
Daniel Eklöf 2021-02-12 10:03:01 +01:00
parent 1c8c76708d
commit 0da766e505
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
2 changed files with 26 additions and 18 deletions

View file

@ -88,6 +88,7 @@
`shift` to be pressed while used in a mouse grabbing `shift` to be pressed while used in a mouse grabbing
application. This meant the mouse event was never seen by the application. This meant the mouse event was never seen by the
application. application.
* `BS`, `HT` and `DEL` from being stripped in bracketed paste mode.
### Security ### Security

View file

@ -1615,6 +1615,15 @@ fdm_receive(struct fdm *fdm, int fd, int events, void *data)
*/ */
char *p = text; char *p = text;
size_t left = count; 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: again:
for (size_t i = 0; i < left; i++) { for (size_t i = 0; i < left; i++) {
switch (p[i]) { switch (p[i]) {
@ -1629,33 +1638,29 @@ fdm_receive(struct fdm *fdm, int fd, int events, void *data)
case '\r': case '\r':
/* Convert \r\n -> \r */ /* Convert \r\n -> \r */
if (!ctx->bracketed && i + 1 < left && p[i + 1] == '\n') { if (!ctx->bracketed && i + 1 < left && p[i + 1] == '\n') {
ctx->decoder(ctx, p, i + 1); i++;
skip_one();
xassert(i + 2 <= left);
p += i + 2;
left -= i + 2;
goto again; goto again;
} }
break; break;
/* C0 non-formatting control characters (\b \t \n \r excluded) */ /* C0 non-formatting control characters (\b \t \n \r excluded) */
case '\x01': case '\x02': case '\x03': case '\x04': case '\x05': case '\x01': case '\x02': case '\x03': case '\x04': case '\x05':
case '\x06': case '\x07': case '\x0b': case '\x0c': case '\x0e': case '\x06': case '\x07': case '\x0e': case '\x0f': case '\x10':
case '\x0f': case '\x10': case '\x11': case '\x12': case '\x13': case '\x11': case '\x12': case '\x13': case '\x14': case '\x15':
case '\x14': case '\x15': case '\x16': case '\x17': case '\x18': case '\x16': case '\x17': case '\x18': case '\x19': case '\x1a':
case '\x19': case '\x1a': case '\x1b': case '\x1c': case '\x1d': case '\x1b': case '\x1c': case '\x1d': case '\x1e': case '\x1f':
case '\x1e': case '\x1f': skip_one();
/* FALLTHROUGH */ goto again;
/* Additional control characters stripped by default (but /* Additional control characters stripped by default (but
* configurable) in XTerm: BS, HT, DEL */ * configurable) in XTerm: BS, HT, DEL */
case '\b': case '\t': case '\x7f': case '\b': case '\t': case '\v': case '\f': case '\x7f':
ctx->decoder(ctx, p, i); if (!ctx->bracketed) {
skip_one();
xassert(i + 1 <= left); goto again;
p += i + 1; }
left -= i + 1; break;
goto again;
} }
} }
@ -1663,6 +1668,8 @@ fdm_receive(struct fdm *fdm, int fd, int events, void *data)
left = 0; left = 0;
} }
#undef skip_one
done: done:
ctx->finish(ctx); ctx->finish(ctx);
clipboard_receive_done(fdm, ctx); clipboard_receive_done(fdm, ctx);