Blame SOURCES/0002-Fix-CVE-2022-44617-Runaway-loop-with-width-of-0-and-.patch

a4ac63
From 52603840b1c5d923cc998335fb651a53d42a036c Mon Sep 17 00:00:00 2001
a4ac63
From: Alan Coopersmith <alan.coopersmith@oracle.com>
a4ac63
Date: Sat, 7 Jan 2023 12:44:28 -0800
a4ac63
Subject: [PATCH libXpm 2/5] Fix CVE-2022-44617: Runaway loop with width of 0
a4ac63
 and enormous height
a4ac63
a4ac63
When reading XPM images from a file with libXpm 3.5.14 or older, if a
a4ac63
image has a width of 0 and a very large height, the ParsePixels() function
a4ac63
will loop over the entire height calling getc() and ungetc() repeatedly,
a4ac63
or in some circumstances, may loop seemingly forever, which may cause a
a4ac63
denial of service to the calling program when given a small crafted XPM
a4ac63
file to parse.
a4ac63
a4ac63
Closes: #2
a4ac63
a4ac63
Reported-by: Martin Ettl <ettl.martin78@googlemail.com>
a4ac63
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
a4ac63
---
a4ac63
 src/data.c  | 20 ++++++++++++++------
a4ac63
 src/parse.c | 31 +++++++++++++++++++++++++++----
a4ac63
 2 files changed, 41 insertions(+), 10 deletions(-)
a4ac63
a4ac63
diff --git a/src/data.c b/src/data.c
a4ac63
index bfad4ff..7524e65 100644
a4ac63
--- a/src/data.c
a4ac63
+++ b/src/data.c
a4ac63
@@ -195,19 +195,23 @@ xpmNextString(xpmData *data)
a4ac63
 	register char c;
a4ac63
 
a4ac63
 	/* get to the end of the current string */
a4ac63
-	if (data->Eos)
a4ac63
-	    while ((c = *data->cptr++) && c != data->Eos);
a4ac63
+	if (data->Eos) {
a4ac63
+	    while ((c = *data->cptr++) && c != data->Eos && c != '\0');
a4ac63
+
a4ac63
+	    if (c == '\0')
a4ac63
+		return XpmFileInvalid;
a4ac63
+	}
a4ac63
 
a4ac63
 	/*
a4ac63
 	 * then get to the beginning of the next string looking for possible
a4ac63
 	 * comment
a4ac63
 	 */
a4ac63
 	if (data->Bos) {
a4ac63
-	    while ((c = *data->cptr++) && c != data->Bos)
a4ac63
+	    while ((c = *data->cptr++) && c != data->Bos && c != '\0')
a4ac63
 		if (data->Bcmt && c == data->Bcmt[0])
a4ac63
 		    ParseComment(data);
a4ac63
 	} else if (data->Bcmt) {	/* XPM2 natural */
a4ac63
-	    while ((c = *data->cptr++) == data->Bcmt[0])
a4ac63
+	    while (((c = *data->cptr++) == data->Bcmt[0]) && c != '\0')
a4ac63
 		ParseComment(data);
a4ac63
 	    data->cptr--;
a4ac63
 	}
a4ac63
@@ -216,9 +220,13 @@ xpmNextString(xpmData *data)
a4ac63
 	FILE *file = data->stream.file;
a4ac63
 
a4ac63
 	/* get to the end of the current string */
a4ac63
-	if (data->Eos)
a4ac63
+	if (data->Eos) {
a4ac63
 	    while ((c = Getc(data, file)) != data->Eos && c != EOF);
a4ac63
 
a4ac63
+	    if (c == EOF)
a4ac63
+		return XpmFileInvalid;
a4ac63
+	}
a4ac63
+
a4ac63
 	/*
a4ac63
 	 * then get to the beginning of the next string looking for possible
a4ac63
 	 * comment
a4ac63
@@ -234,7 +242,7 @@ xpmNextString(xpmData *data)
a4ac63
 	    Ungetc(data, c, file);
a4ac63
 	}
a4ac63
     }
a4ac63
-    return 0;
a4ac63
+    return XpmSuccess;
a4ac63
 }
a4ac63
 
a4ac63
 
a4ac63
diff --git a/src/parse.c b/src/parse.c
a4ac63
index c19209c..e97d771 100644
a4ac63
--- a/src/parse.c
a4ac63
+++ b/src/parse.c
a4ac63
@@ -391,6 +391,13 @@ ParsePixels(
a4ac63
 {
a4ac63
     unsigned int *iptr, *iptr2 = NULL; /* found by Egbert Eich */
a4ac63
     unsigned int a, x, y;
a4ac63
+    int ErrorStatus;
a4ac63
+
a4ac63
+    if ((width == 0) && (height != 0))
a4ac63
+	return (XpmFileInvalid);
a4ac63
+
a4ac63
+    if ((height == 0) && (width != 0))
a4ac63
+	return (XpmFileInvalid);
a4ac63
 
a4ac63
     if ((height > 0 && width >= UINT_MAX / height) ||
a4ac63
 	width * height >= UINT_MAX / sizeof(unsigned int))
a4ac63
@@ -428,7 +435,11 @@ ParsePixels(
a4ac63
 		colidx[(unsigned char)colorTable[a].string[0]] = a + 1;
a4ac63
 
a4ac63
 	    for (y = 0; y < height; y++) {
a4ac63
-		xpmNextString(data);
a4ac63
+		ErrorStatus = xpmNextString(data);
a4ac63
+		if (ErrorStatus != XpmSuccess) {
a4ac63
+		    XpmFree(iptr2);
a4ac63
+		    return (ErrorStatus);
a4ac63
+		}
a4ac63
 		for (x = 0; x < width; x++, iptr++) {
a4ac63
 		    int c = xpmGetC(data);
a4ac63
 
a4ac63
@@ -475,7 +486,11 @@ do \
a4ac63
 	    }
a4ac63
 
a4ac63
 	    for (y = 0; y < height; y++) {
a4ac63
-		xpmNextString(data);
a4ac63
+		ErrorStatus = xpmNextString(data);
a4ac63
+		if (ErrorStatus != XpmSuccess) {
a4ac63
+		    XpmFree(iptr2);
a4ac63
+		    return (ErrorStatus);
a4ac63
+		}
a4ac63
 		for (x = 0; x < width; x++, iptr++) {
a4ac63
 		    int cc1 = xpmGetC(data);
a4ac63
 		    if (cc1 > 0 && cc1 < 256) {
a4ac63
@@ -515,7 +530,11 @@ do \
a4ac63
 		xpmHashAtom *slot;
a4ac63
 
a4ac63
 		for (y = 0; y < height; y++) {
a4ac63
-		    xpmNextString(data);
a4ac63
+		    ErrorStatus = xpmNextString(data);
a4ac63
+		    if (ErrorStatus != XpmSuccess) {
a4ac63
+			XpmFree(iptr2);
a4ac63
+			return (ErrorStatus);
a4ac63
+		    }
a4ac63
 		    for (x = 0; x < width; x++, iptr++) {
a4ac63
 			for (a = 0, s = buf; a < cpp; a++, s++) {
a4ac63
 			    int c = xpmGetC(data);
a4ac63
@@ -535,7 +554,11 @@ do \
a4ac63
 		}
a4ac63
 	    } else {
a4ac63
 		for (y = 0; y < height; y++) {
a4ac63
-		    xpmNextString(data);
a4ac63
+		    ErrorStatus = xpmNextString(data);
a4ac63
+		    if (ErrorStatus != XpmSuccess) {
a4ac63
+			XpmFree(iptr2);
a4ac63
+			return (ErrorStatus);
a4ac63
+		    }
a4ac63
 		    for (x = 0; x < width; x++, iptr++) {
a4ac63
 			for (a = 0, s = buf; a < cpp; a++, s++) {
a4ac63
 			    int c = xpmGetC(data);
a4ac63
-- 
a4ac63
2.39.0
a4ac63