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