File u_xkb-Handle-xkb-formated-string-output-safely.patch of Package xorg-x11-server.24940

Patch-mainline: To be upstreamed
Author: Keith Packard <keithp@keithp.com>
Signed-off-by: Michal Srb <msrb@suse.com>
Subject: xkb: Handle xkb formated string output safely
References: bnc#1051150 CVE-2017-13723

Generating strings for XKB data used a single shared static buffer,
which offered several opportunities for errors. Use a ring of
resizable buffers instead, to avoid problems when strings end up
longer than anticipated.

Signed-off-by: Keith Packard <keithp@keithp.com>
---
 xkb/xkbtext.c | 40 ++++++++++++++++++++--------------------
 1 file changed, 20 insertions(+), 20 deletions(-)

diff --git a/xkb/xkbtext.c b/xkb/xkbtext.c
index ffbc546b3..e90581e0f 100644
--- a/xkb/xkbtext.c
+++ b/xkb/xkbtext.c
@@ -47,23 +47,27 @@
 
 /***====================================================================***/
 
-#define	BUFFER_SIZE	512
-
-static char textBuffer[BUFFER_SIZE];
-static int tbNext = 0;
+#define NUM_BUFFER      8
+static struct textBuffer {
+    int size;
+    char *buffer;
+} textBuffer[NUM_BUFFER];
+static int textBufferIndex;
 
 static char *
 tbGetBuffer(unsigned size)
 {
-    char *rtrn;
+    struct textBuffer *tb;
 
-    if (size >= BUFFER_SIZE)
-        return NULL;
-    if ((BUFFER_SIZE - tbNext) <= size)
-        tbNext = 0;
-    rtrn = &textBuffer[tbNext];
-    tbNext += size;
-    return rtrn;
+    tb = &textBuffer[textBufferIndex];
+    textBufferIndex = (textBufferIndex + 1) % NUM_BUFFER;
+
+    if (size > tb->size) {
+        free(tb->buffer);
+        tb->buffer = xnfalloc(size);
+        tb->size = size;
+    }
+    return tb->buffer;
 }
 
 /***====================================================================***/
@@ -79,8 +83,6 @@ XkbAtomText(Atom atm, unsigned format)
         int len;
 
         len = strlen(atmstr) + 1;
-        if (len > BUFFER_SIZE)
-            len = BUFFER_SIZE - 2;
         rtrn = tbGetBuffer(len);
         strlcpy(rtrn, atmstr, len);
     }
@@ -128,8 +130,6 @@ XkbVModIndexText(XkbDescPtr xkb, unsigned ndx, unsigned format)
     len = strlen(tmp) + 1;
     if (format == XkbCFile)
         len += 4;
-    if (len >= BUFFER_SIZE)
-        len = BUFFER_SIZE - 1;
     rtrn = tbGetBuffer(len);
     if (format == XkbCFile) {
         strcpy(rtrn, "vmod_");
@@ -140,6 +140,8 @@ XkbVModIndexText(XkbDescPtr xkb, unsigned ndx, unsigned format)
     return rtrn;
 }
 
+#define VMOD_BUFFER_SIZE        512
+
 char *
 XkbVModMaskText(XkbDescPtr xkb,
                 unsigned modMask, unsigned mask, unsigned format)
@@ -147,7 +149,7 @@ XkbVModMaskText(XkbDescPtr xkb,
     register int i, bit;
     int len;
     char *mm, *rtrn;
-    char *str, buf[BUFFER_SIZE];
+    char *str, buf[VMOD_BUFFER_SIZE];
 
     if ((modMask == 0) && (mask == 0)) {
         rtrn = tbGetBuffer(5);
@@ -173,7 +175,7 @@ XkbVModMaskText(XkbDescPtr xkb,
                 len = strlen(tmp) + 1 + (str == buf ? 0 : 1);
                 if (format == XkbCFile)
                     len += 4;
-                if ((str - (buf + len)) <= BUFFER_SIZE) {
+                if ((str - (buf + len)) <= VMOD_BUFFER_SIZE) {
                     if (str != buf) {
                         if (format == XkbCFile)
                             *str++ = '|';
@@ -199,8 +201,6 @@ XkbVModMaskText(XkbDescPtr xkb,
         len = 0;
     if (str)
         len += strlen(str) + (mm == NULL ? 0 : 1);
-    if (len >= BUFFER_SIZE)
-        len = BUFFER_SIZE - 1;
     rtrn = tbGetBuffer(len + 1);
     rtrn[0] = '\0';
 
-- 
2.13.3

openSUSE Build Service is sponsored by