155 lines
4.6 KiB
Diff
155 lines
4.6 KiB
Diff
From f80fa6ae47ad4a5beacb287c0030c9913b046643 Mon Sep 17 00:00:00 2001
|
|
From: Alan Coopersmith <alan.coopersmith@oracle.com>
|
|
Date: Sat, 7 Jan 2023 12:44:28 -0800
|
|
Subject: [PATCH] Fix CVE-2022-44617: Runaway loop with width of 0 and enormous
|
|
height
|
|
|
|
When reading XPM images from a file with libXpm 3.5.14 or older, if a
|
|
image has a width of 0 and a very large height, the ParsePixels() function
|
|
will loop over the entire height calling getc() and ungetc() repeatedly,
|
|
or in some circumstances, may loop seemingly forever, which may cause a
|
|
denial of service to the calling program when given a small crafted XPM
|
|
file to parse.
|
|
|
|
Closes: #2
|
|
|
|
Reported-by: Martin Ettl <ettl.martin78@googlemail.com>
|
|
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
|
|
|
|
Origin:
|
|
https://gitlab.freedesktop.org/xorg/lib/libxpm/-/commit/f80fa6ae47ad4a5beacb287c0030c9913b046643
|
|
---
|
|
lib/Xm/Xpmdata.c | 20 ++++++++++++++------
|
|
lib/Xm/Xpmparse.c | 31 +++++++++++++++++++++++++++----
|
|
2 files changed, 41 insertions(+), 10 deletions(-)
|
|
|
|
diff --git a/lib/Xm/Xpmdata.c b/lib/Xm/Xpmdata.c
|
|
index d65ae57..45ccfae 100644
|
|
--- a/lib/Xm/Xpmdata.c
|
|
+++ b/lib/Xm/Xpmdata.c
|
|
@@ -189,19 +189,23 @@ xpmNextString(mdata)
|
|
register char c;
|
|
|
|
/* get to the end of the current string */
|
|
- if (mdata->Eos)
|
|
- while ((c = *mdata->cptr++) && c != mdata->Eos);
|
|
+ if (mdata->Eos) {
|
|
+ while ((c = *mdata->cptr++) && c != mdata->Eos && c != '\0');
|
|
+
|
|
+ if (c == '\0')
|
|
+ return XpmFileInvalid;
|
|
+ }
|
|
|
|
/*
|
|
* then get to the beginning of the next string looking for possible
|
|
* comment
|
|
*/
|
|
if (mdata->Bos) {
|
|
- while ((c = *mdata->cptr++) && c != mdata->Bos)
|
|
+ while ((c = *mdata->cptr++) && c != mdata->Bos && c != '\0')
|
|
if (mdata->Bcmt && c == mdata->Bcmt[0])
|
|
ParseComment(mdata);
|
|
} else if (mdata->Bcmt) { /* XPM2 natural */
|
|
- while ((c = *mdata->cptr++) == mdata->Bcmt[0])
|
|
+ while (((c = *mdata->cptr++) == mdata->Bcmt[0]) && c != '\0')
|
|
ParseComment(mdata);
|
|
mdata->cptr--;
|
|
}
|
|
@@ -210,9 +214,13 @@ xpmNextString(mdata)
|
|
FILE *file = mdata->stream.file;
|
|
|
|
/* get to the end of the current string */
|
|
- if (mdata->Eos)
|
|
+ if (mdata->Eos) {
|
|
while ((c = getc(file)) != mdata->Eos && c != EOF);
|
|
|
|
+ if (c == EOF)
|
|
+ return XpmFileInvalid;
|
|
+ }
|
|
+
|
|
/*
|
|
* then get to the beginning of the next string looking for possible
|
|
* comment
|
|
@@ -228,7 +236,7 @@ xpmNextString(mdata)
|
|
ungetc(c, file);
|
|
}
|
|
}
|
|
- return 0;
|
|
+ return XpmSuccess;
|
|
}
|
|
|
|
|
|
diff --git a/lib/Xm/Xpmparse.c b/lib/Xm/Xpmparse.c
|
|
index a54bca9..da21dbb 100644
|
|
--- a/lib/Xm/Xpmparse.c
|
|
+++ b/lib/Xm/Xpmparse.c
|
|
@@ -523,6 +523,13 @@ ParsePixels(data, width, height, ncolors, cpp, colorTable, hashtable, pixels)
|
|
{
|
|
unsigned int *iptr, *iptr2 = NULL; /* found by Egbert Eich */
|
|
unsigned int a, x, y;
|
|
+ int ErrorStatus;
|
|
+
|
|
+ if ((width == 0) && (height != 0))
|
|
+ return (XpmFileInvalid);
|
|
+
|
|
+ if ((height == 0) && (width != 0))
|
|
+ return (XpmFileInvalid);
|
|
|
|
if ((height > 0 && width >= UINT_MAX / height) ||
|
|
width * height >= UINT_MAX / sizeof(unsigned int))
|
|
@@ -560,7 +567,11 @@ ParsePixels(data, width, height, ncolors, cpp, colorTable, hashtable, pixels)
|
|
colidx[(unsigned char)colorTable[a].string[0]] = a + 1;
|
|
|
|
for (y = 0; y < height; y++) {
|
|
- xpmNextString(data);
|
|
+ ErrorStatus = xpmNextString(data);
|
|
+ if (ErrorStatus != XpmSuccess) {
|
|
+ XpmFree(iptr2);
|
|
+ return (ErrorStatus);
|
|
+ }
|
|
for (x = 0; x < width; x++, iptr++) {
|
|
int c = xpmGetC(data);
|
|
|
|
@@ -607,7 +618,11 @@ do \
|
|
}
|
|
|
|
for (y = 0; y < height; y++) {
|
|
- xpmNextString(data);
|
|
+ ErrorStatus = xpmNextString(data);
|
|
+ if (ErrorStatus != XpmSuccess) {
|
|
+ XpmFree(iptr2);
|
|
+ return (ErrorStatus);
|
|
+ }
|
|
for (x = 0; x < width; x++, iptr++) {
|
|
int cc1 = xpmGetC(data);
|
|
if (cc1 > 0 && cc1 < 256) {
|
|
@@ -646,7 +661,11 @@ do \
|
|
xpmHashAtom *slot;
|
|
|
|
for (y = 0; y < height; y++) {
|
|
- xpmNextString(data);
|
|
+ ErrorStatus = xpmNextString(data);
|
|
+ if (ErrorStatus != XpmSuccess) {
|
|
+ XpmFree(iptr2);
|
|
+ return (ErrorStatus);
|
|
+ }
|
|
for (x = 0; x < width; x++, iptr++) {
|
|
for (a = 0, s = buf; a < cpp; a++, s++)
|
|
*s = xpmGetC(data); /* int assigned to char, not a problem here */
|
|
@@ -660,7 +679,11 @@ do \
|
|
}
|
|
} else {
|
|
for (y = 0; y < height; y++) {
|
|
- xpmNextString(data);
|
|
+ ErrorStatus = xpmNextString(data);
|
|
+ if (ErrorStatus != XpmSuccess) {
|
|
+ XpmFree(iptr2);
|
|
+ return (ErrorStatus);
|
|
+ }
|
|
for (x = 0; x < width; x++, iptr++) {
|
|
for (a = 0, s = buf; a < cpp; a++, s++)
|
|
*s = xpmGetC(data); /* int assigned to char, not a problem here */
|
|
--
|
|
2.46.0
|
|
|