On Mon, Oct 24, 2022 at 01:10:29PM +0300, Santtu Lakkala wrote:
> The dynmaic[sic] version incorrectly passes sizeof(buf), where buf is char
> *, as the size of buffer in the "happy case" leading to unnecessary hits to
> the dynamic path.

Ah yes, the classic. Attached ammended version of the dynmaic patch.
A bit more invasive (but hopefully correct) than the previous patch.

- NRK
>From 920799cb2a3526f2398caf98ebf0815fb323ff3f Mon Sep 17 00:00:00 2001
From: NRK <[email protected]>
Date: Mon, 24 Oct 2022 15:49:18 +0600
Subject: [PATCH] fix: buffer overflow when handling composed input

XmbLookupString may leave buf as well as ksym uninitialized. initialize
ksym to NoSymbol. track weather we need a larger buffer or not, and
dynamically allocate if needed.

Reported-by: Andy Gozas <[email protected]>
---
 x.c | 30 ++++++++++++++++++++----------
 1 file changed, 20 insertions(+), 10 deletions(-)

diff --git a/x.c b/x.c
index f70e3fb..6a4ed46 100644
--- a/x.c
+++ b/x.c
@@ -1847,8 +1847,8 @@ kpress(XEvent *ev)
 {
 	XKeyEvent *e = &ev->xkey;
 	KeySym ksym;
-	char buf[64], *customkey;
-	int len;
+	char buf[64], *p = NULL, *customkey;
+	int len, overflow = 0;
 	Rune c;
 	Status status;
 	const Shortcut *bp;
@@ -1856,10 +1856,12 @@ kpress(XEvent *ev)
 	if (IS_SET(MODE_KBDLOCK))
 		return;
 
-	if (xw.ime.xic)
+	if (xw.ime.xic) {
 		len = XmbLookupString(xw.ime.xic, e, buf, sizeof buf, &ksym, &status);
-	else
+		overflow = status == XBufferOverflow ? len : 0;
+	} else {
 		len = XLookupString(e, buf, sizeof buf, &ksym, NULL);
+	}
 	/* 1. shortcuts */
 	for (bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) {
 		if (ksym == bp->keysym && match(bp->mod, e->state)) {
@@ -1875,21 +1877,29 @@ kpress(XEvent *ev)
 	}
 
 	/* 3. composed string from input method */
+	if (overflow) {
+		p = xmalloc(overflow);
+		len = XmbLookupString(xw.ime.xic, e, p, overflow, &ksym, &status);
+	} else {
+		p = buf;
+	}
 	if (len == 0)
 		return;
 	if (len == 1 && e->state & Mod1Mask) {
 		if (IS_SET(MODE_8BIT)) {
-			if (*buf < 0177) {
-				c = *buf | 0x80;
-				len = utf8encode(c, buf);
+			if (*p < 0177) {
+				c = *p | 0x80;
+				len = utf8encode(c, p);
 			}
 		} else {
-			buf[1] = buf[0];
-			buf[0] = '\033';
+			p[1] = p[0];
+			p[0] = '\033';
 			len = 2;
 		}
 	}
-	ttywrite(buf, len, 1);
+	ttywrite(p, len, 1);
+	if (overflow)
+		free(p);
 }
 
 void
-- 
2.35.1

Reply via email to