MFC: 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.
This commit is contained in:
parent
fd77a34918
commit
9b9efb1bdf
@ -47,23 +47,27 @@
|
|||||||
|
|
||||||
/***====================================================================***/
|
/***====================================================================***/
|
||||||
|
|
||||||
#define BUFFER_SIZE 512
|
#define NUM_BUFFER 8
|
||||||
|
static struct textBuffer {
|
||||||
static char textBuffer[BUFFER_SIZE];
|
int size;
|
||||||
static int tbNext = 0;
|
char *buffer;
|
||||||
|
} textBuffer[NUM_BUFFER];
|
||||||
|
static int textBufferIndex;
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
tbGetBuffer(unsigned size)
|
tbGetBuffer(unsigned size)
|
||||||
{
|
{
|
||||||
char *rtrn;
|
struct textBuffer *tb;
|
||||||
|
|
||||||
if (size >= BUFFER_SIZE)
|
tb = &textBuffer[textBufferIndex];
|
||||||
return NULL;
|
textBufferIndex = (textBufferIndex + 1) % NUM_BUFFER;
|
||||||
if ((BUFFER_SIZE - tbNext) <= size)
|
|
||||||
tbNext = 0;
|
if (size > tb->size) {
|
||||||
rtrn = &textBuffer[tbNext];
|
free(tb->buffer);
|
||||||
tbNext += size;
|
tb->buffer = xnfalloc(size);
|
||||||
return rtrn;
|
tb->size = size;
|
||||||
|
}
|
||||||
|
return tb->buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***====================================================================***/
|
/***====================================================================***/
|
||||||
@ -79,8 +83,6 @@ XkbAtomText(Atom atm, unsigned format)
|
|||||||
int len;
|
int len;
|
||||||
|
|
||||||
len = strlen(atmstr) + 1;
|
len = strlen(atmstr) + 1;
|
||||||
if (len > BUFFER_SIZE)
|
|
||||||
len = BUFFER_SIZE - 2;
|
|
||||||
rtrn = tbGetBuffer(len);
|
rtrn = tbGetBuffer(len);
|
||||||
strlcpy(rtrn, atmstr, len);
|
strlcpy(rtrn, atmstr, len);
|
||||||
}
|
}
|
||||||
@ -128,8 +130,6 @@ XkbVModIndexText(XkbDescPtr xkb, unsigned ndx, unsigned format)
|
|||||||
len = strlen(tmp) + 1;
|
len = strlen(tmp) + 1;
|
||||||
if (format == XkbCFile)
|
if (format == XkbCFile)
|
||||||
len += 4;
|
len += 4;
|
||||||
if (len >= BUFFER_SIZE)
|
|
||||||
len = BUFFER_SIZE - 1;
|
|
||||||
rtrn = tbGetBuffer(len);
|
rtrn = tbGetBuffer(len);
|
||||||
if (format == XkbCFile) {
|
if (format == XkbCFile) {
|
||||||
strcpy(rtrn, "vmod_");
|
strcpy(rtrn, "vmod_");
|
||||||
@ -140,6 +140,8 @@ XkbVModIndexText(XkbDescPtr xkb, unsigned ndx, unsigned format)
|
|||||||
return rtrn;
|
return rtrn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define VMOD_BUFFER_SIZE 512
|
||||||
|
|
||||||
char *
|
char *
|
||||||
XkbVModMaskText(XkbDescPtr xkb,
|
XkbVModMaskText(XkbDescPtr xkb,
|
||||||
unsigned modMask, unsigned mask, unsigned format)
|
unsigned modMask, unsigned mask, unsigned format)
|
||||||
@ -147,7 +149,7 @@ XkbVModMaskText(XkbDescPtr xkb,
|
|||||||
register int i, bit;
|
register int i, bit;
|
||||||
int len;
|
int len;
|
||||||
char *mm, *rtrn;
|
char *mm, *rtrn;
|
||||||
char *str, buf[BUFFER_SIZE];
|
char *str, buf[VMOD_BUFFER_SIZE];
|
||||||
|
|
||||||
if ((modMask == 0) && (mask == 0)) {
|
if ((modMask == 0) && (mask == 0)) {
|
||||||
rtrn = tbGetBuffer(5);
|
rtrn = tbGetBuffer(5);
|
||||||
@ -173,7 +175,7 @@ XkbVModMaskText(XkbDescPtr xkb,
|
|||||||
len = strlen(tmp) + 1 + (str == buf ? 0 : 1);
|
len = strlen(tmp) + 1 + (str == buf ? 0 : 1);
|
||||||
if (format == XkbCFile)
|
if (format == XkbCFile)
|
||||||
len += 4;
|
len += 4;
|
||||||
if ((str - (buf + len)) <= BUFFER_SIZE) {
|
if ((str - (buf + len)) <= VMOD_BUFFER_SIZE) {
|
||||||
if (str != buf) {
|
if (str != buf) {
|
||||||
if (format == XkbCFile)
|
if (format == XkbCFile)
|
||||||
*str++ = '|';
|
*str++ = '|';
|
||||||
@ -183,7 +185,7 @@ XkbVModMaskText(XkbDescPtr xkb,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (format == XkbCFile)
|
if (format == XkbCFile)
|
||||||
snprintf(str, BUFFER_SIZE - len, "%sMask", tmp);
|
snprintf(str, VMOD_BUFFER_SIZE - len, "%sMask", tmp);
|
||||||
else
|
else
|
||||||
strcpy(str, tmp);
|
strcpy(str, tmp);
|
||||||
str = &str[len - 1];
|
str = &str[len - 1];
|
||||||
@ -199,8 +201,6 @@ XkbVModMaskText(XkbDescPtr xkb,
|
|||||||
len = 0;
|
len = 0;
|
||||||
if (str)
|
if (str)
|
||||||
len += strlen(str) + (mm == NULL ? 0 : 1);
|
len += strlen(str) + (mm == NULL ? 0 : 1);
|
||||||
if (len >= BUFFER_SIZE)
|
|
||||||
len = BUFFER_SIZE - 1;
|
|
||||||
rtrn = tbGetBuffer(len + 1);
|
rtrn = tbGetBuffer(len + 1);
|
||||||
rtrn[0] = '\0';
|
rtrn[0] = '\0';
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user