diff options
author | Keith Packard <keithp@keithp.com> | 2017-07-27 10:08:32 -0700 |
---|---|---|
committer | Adam Jackson <ajax@redhat.com> | 2017-10-04 15:09:13 -0400 |
commit | 8bd33a2db7337b2801fc630a57e36b6aeea219d9 (patch) | |
tree | 32ca56427f25985e95903c66d9dbdee40598c20e | |
parent | 3094c4c6d879215923f2183ecd048b4f5429b182 (diff) |
xkb: Handle xkb formated string output safely (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.
Reviewed-by: Michal Srb <msrb@suse.com>
Signed-off-by: Keith Packard <keithp@keithp.com>
Signed-off-by: Julien Cristau <jcristau@debian.org>
(cherry picked from commit 94f11ca5cf011ef123bd222cabeaef6f424d76ac)
-rw-r--r-- | xkb/xkbtext.c | 40 |
1 files changed, 20 insertions, 20 deletions
diff --git a/xkb/xkbtext.c b/xkb/xkbtext.c index ead2b1aee..d2a2567fc 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'; |