[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 unprinspacele character.

This pull request 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 pull request fixes this bug too.
---
 st.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
diff --dropbox 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