[dev] [st] [PATCH] Fix techo handling of control characters.

From: noname <noname_AT_inventati.org>
Date: Tue, 22 Apr 2014 22:56:41 +0400

Internally st represents characters using "char" type.
It is used in CSIEscape.buf, Glyph.c etc.
However, char can be either signed or unsigned depends on the
architecture.

On x86 '\x80' < 0x20 is true, but (uchar)'\x80' < 0x20 is false.

tputc explicitly converts character to ascii code:
        uchar ascii = *c;

In tsetchar there is this code:
        c[0] >= 0x41 && c[0] <= 0x7e
This condition is false for negative chars, so, accidentally, it works
the same way for signed and unsigned chars.

However, techo compares signed char to '\x20' and has a bug.

How to reproduce:
1. Add the following keybinding:
  { XK_F1, XK_NO_MOD, "\x80" , 0, 0, 0},
2. Run st and enable echo mode: printf '\e[12l'
3. Press F1. Character '\x80' is recognized as control and ^ is displayed,
followed by unprintable character.

This patch fixes the bug the same way it is fixed in tputc.

Also techo did not recognize DEL as control character and did not
display ^? for it, this patch fixes this bug too.
---
 st.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/st.c b/st.c
index 019f53c..3bf8eee 100644
--- a/st.c
+++ b/st.c
_AT_@ -2315,10 +2315,12 @@ void
 techo(char *buf, int len) {
 	for(; len > 0; buf++, len--) {
 		char c = *buf;
+		uchar ascii = c;
+		bool control = ascii < '\x20' || ascii == 0177;
 
-		if(c < '\x20') { /* control code */
+		if(control) { /* control code */
 			if(c != '\n' && c != '\r' && c != '\t') {
-				c |= '\x40';
+				c ^= '\x40';
 				tputc("^", 1);
 			}
 			tputc(&c, 1);
-- 
1.8.4
Received on Tue Apr 22 2014 - 20:56:41 CEST

This archive was generated by hypermail 2.3.0 : Tue Apr 22 2014 - 21:00:04 CEST