update to 3.5.15

This commit is contained in:
zhouwenpei 2023-02-04 02:46:26 +00:00
parent 19a7356cda
commit 8502304c82
9 changed files with 7 additions and 540 deletions

View File

@ -1,150 +0,0 @@
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>
---
src/data.c | 20 ++++++++++++++------
src/parse.c | 31 +++++++++++++++++++++++++++----
2 files changed, 41 insertions(+), 10 deletions(-)
diff --git a/src/data.c b/src/data.c
index bfad4ff..7524e65 100644
--- a/src/data.c
+++ b/src/data.c
@@ -195,19 +195,23 @@ xpmNextString(xpmData *data)
register char c;
/* get to the end of the current string */
- if (data->Eos)
- while ((c = *data->cptr++) && c != data->Eos);
+ if (data->Eos) {
+ while ((c = *data->cptr++) && c != data->Eos && c != '\0');
+
+ if (c == '\0')
+ return XpmFileInvalid;
+ }
/*
* then get to the beginning of the next string looking for possible
* comment
*/
if (data->Bos) {
- while ((c = *data->cptr++) && c != data->Bos)
+ while ((c = *data->cptr++) && c != data->Bos && c != '\0')
if (data->Bcmt && c == data->Bcmt[0])
ParseComment(data);
} else if (data->Bcmt) { /* XPM2 natural */
- while ((c = *data->cptr++) == data->Bcmt[0])
+ while (((c = *data->cptr++) == data->Bcmt[0]) && c != '\0')
ParseComment(data);
data->cptr--;
}
@@ -216,9 +220,13 @@ xpmNextString(xpmData *data)
FILE *file = data->stream.file;
/* get to the end of the current string */
- if (data->Eos)
+ if (data->Eos) {
while ((c = Getc(data, file)) != data->Eos && c != EOF);
+ if (c == EOF)
+ return XpmFileInvalid;
+ }
+
/*
* then get to the beginning of the next string looking for possible
* comment
@@ -234,7 +242,7 @@ xpmNextString(xpmData *data)
Ungetc(data, c, file);
}
}
- return 0;
+ return XpmSuccess;
}
diff --git a/src/parse.c b/src/parse.c
index 037fc66..64f51ba 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -427,6 +427,13 @@ ParsePixels(
{
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))
@@ -464,7 +471,11 @@ ParsePixels(
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);
@@ -511,7 +522,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) {
@@ -551,7 +566,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++) {
int c = xpmGetC(data);
@@ -571,7 +590,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++) {
int c = xpmGetC(data);
--
GitLab

View File

@ -1,93 +0,0 @@
From 4841039e5385f264d12757903894f47c64f59361 Mon Sep 17 00:00:00 2001
From: Alan Coopersmith <alan.coopersmith@oracle.com>
Date: Thu, 5 Jan 2023 15:42:36 -0800
Subject: configure: add --disable-open-zfile instead of requiring -DNO_ZPIPE
Documents the two compression options in the README, makes their
configure options reflect the interdependency of their implementation,
and makes the configure script report their configuration.
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
---
README.md | 15 +++++++++++++++
configure.ac | 36 +++++++++++++++++++++++-------------
2 files changed, 38 insertions(+), 13 deletions(-)
diff --git a/README.md b/README.md
index adc83c8..7895350 100644
--- a/README.md
+++ b/README.md
@@ -16,3 +16,18 @@ For patch submission instructions, see:
https://www.x.org/wiki/Development/Documentation/SubmittingPatches
+------------------------------------------------------------------------------
+
+libXpm supports two optional features to handle compressed pixmap files.
+
+--enable-open-zfile makes libXpm recognize file names ending in .Z and .gz
+and open a pipe to the appropriate command to compress the file when writing
+and uncompress the file when reading. This is enabled by default on platforms
+other than MinGW and can be disabled by passing the --disable-open-zfile flag
+to the configure script.
+
+--enable-stat-zfile make libXpm search for a file name with .Z or .gz added
+if it can't find the file it was asked to open. It relies on the
+--enable-open-zfile feature to open the file, and is enabled by default
+when --enable-open-zfile is enabled, and can be disabled by passing the
+--disable-stat-zfile flag to the configure script.
diff --git a/configure.ac b/configure.ac
index 789a96e..1b64830 100644
--- a/configure.ac
+++ b/configure.ac
@@ -49,25 +49,35 @@ if test "x$USE_GETTEXT" = "xyes" ; then
fi
AM_CONDITIONAL(USE_GETTEXT, test "x$USE_GETTEXT" = "xyes")
+# Optional feature: When a filename ending in .Z or .gz is requested,
+# open a pipe to a newly forked compress/uncompress/gzip/gunzip command to
+# handle it.
+AC_MSG_CHECKING([whether to handle compressed pixmaps])
+case $host_os in
+ *mingw*) zpipe_default="no" ;;
+ *) zpipe_default="yes" ;;
+esac
+AC_ARG_ENABLE(open-zfile,
+ AS_HELP_STRING([--enable-open-zfile],
+ [Search for files with .Z & .gz extensions automatically @<:@default=auto@:>@]),
+ [OPEN_ZFILE=$enableval], [OPEN_ZFILE=yes])
+AC_MSG_RESULT([$OPEN_ZFILE])
+if test x$OPEN_ZFILE = xno ; then
+ AC_DEFINE(NO_ZPIPE, 1, [Define to 1 to disable decompression via pipes])
+fi
+
# Optional feature: When ___.xpm is requested, also look for ___.xpm.Z & .gz
# Replaces ZFILEDEF = -DSTAT_ZFILE in old Imakefile
+AC_MSG_CHECKING([whether to search for compressed pixmaps])
AC_ARG_ENABLE(stat-zfile,
- AS_HELP_STRING([--enable-stat-zfile],
- [Search for files with .Z & .gz extensions automatically @<:@default=yes@:>@]),
- [STAT_ZFILE=$enableval], [STAT_ZFILE=yes])
+ AS_HELP_STRING([--enable-stat-zfile],
+ [Search for files with .Z & .gz extensions automatically @<:@default=auto@:>@]),
+ [STAT_ZFILE=$enableval], [STAT_ZFILE=$OPEN_ZFILE])
+AC_MSG_RESULT([$STAT_ZFILE])
if test x$STAT_ZFILE = xyes ; then
- AC_DEFINE(STAT_ZFILE, 1, [Define to 1 to automatically look for files with .Z & .gz extensions])
+ AC_DEFINE(STAT_ZFILE, 1, [Define to 1 to automatically look for files with .Z & .gz extensions])
fi
-
-case $host_os in
- *mingw*)
- AC_DEFINE(NO_ZPIPE, 1, [Define to 1 to disable decompression via pipes])
- ;;
- *)
- ;;
-esac
-
AC_CONFIG_FILES([Makefile
doc/Makefile
include/Makefile
--
cgit v1.2.1

View File

@ -1,40 +0,0 @@
From c5ab17bcc34914c0b0707d2135dbebe9a367c5f0 Mon Sep 17 00:00:00 2001
From: Matthieu Herrb <matthieu@herrb.eu>
Date: Thu, 12 Jan 2023 15:05:39 +1000
Subject: [PATCH] Prevent a double free in the error code path
xpmParseDataAndCreate() calls XDestroyImage() in the error path.
Reproducible with sxpm "zero-width.xpm", that file is in the test/
directory.
The same approach is needed in the bytes_per_line == 0 condition though
here it just plugs a memory leak.
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
---
src/create.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/create.c b/src/create.c
index 4a85c78..f92ffef 100644
--- a/src/create.c
+++ b/src/create.c
@@ -994,11 +994,15 @@ CreateXImage(
#if !defined(FOR_MSW) && !defined(AMIGA)
if (height != 0 && (*image_return)->bytes_per_line >= INT_MAX / height) {
XDestroyImage(*image_return);
+ *image_return = NULL;
return XpmNoMemory;
}
/* now that bytes_per_line must have been set properly alloc data */
- if((*image_return)->bytes_per_line == 0 || height == 0)
+ if((*image_return)->bytes_per_line == 0 || height == 0) {
+ XDestroyImage(*image_return);
+ *image_return = NULL;
return XpmNoMemory;
+ }
(*image_return)->data =
(char *) XpmMalloc((*image_return)->bytes_per_line * height);
--
GitLab

View File

@ -1,143 +0,0 @@
From 515294bb8023a45ff916696d0a14308ff4f3a376 Mon Sep 17 00:00:00 2001
From: Alan Coopersmith <alan.coopersmith@oracle.com>
Date: Fri, 6 Jan 2023 12:50:48 -0800
Subject: [PATCH] Fix CVE-2022-4883: compression commands depend on $PATH
By default, on all platforms except MinGW, libXpm will detect if a
filename ends in .Z or .gz, and will when reading such a file fork off
an uncompress or gunzip command to read from via a pipe, and when
writing such a file will fork off a compress or gzip command to write
to via a pipe.
In libXpm 3.5.14 or older these are run via execlp(), relying on $PATH
to find the commands. If libXpm is called from a program running with
raised privileges, such as via setuid, then a malicious user could set
$PATH to include programs of their choosing to be run with those
privileges.
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
---
README.md | 12 ++++++++++++
configure.ac | 14 ++++++++++++++
src/RdFToI.c | 17 ++++++++++++++---
src/WrFFrI.c | 4 ++--
4 files changed, 42 insertions(+), 5 deletions(-)
diff --git a/README.md b/README.md
index f3f4c93..0b1c886 100644
--- a/README.md
+++ b/README.md
@@ -31,3 +31,15 @@ if it can't find the file it was asked to open. It relies on the
--enable-open-zfile feature to open the file, and is enabled by default
when --enable-open-zfile is enabled, and can be disabled by passing the
--disable-stat-zfile flag to the configure script.
+
+All of these commands will be executed with whatever userid & privileges the
+function is called with, relying on the caller to ensure the correct euid,
+egid, etc. are set before calling.
+
+To reduce risk, the paths to these commands are now set at configure time to
+the first version found in the PATH used to run configure, and do not depend
+on the PATH environment variable set at runtime.
+
+To specify paths to be used for these commands instead of searching $PATH, pass
+the XPM_PATH_COMPRESS, XPM_PATH_UNCOMPRESS, XPM_PATH_GZIP, and XPM_PATH_GUNZIP
+variables to the configure command.
diff --git a/configure.ac b/configure.ac
index 85e2c73..4fc370d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -49,6 +49,14 @@ if test "x$USE_GETTEXT" = "xyes" ; then
fi
AM_CONDITIONAL(USE_GETTEXT, test "x$USE_GETTEXT" = "xyes")
+dnl Helper macro to find absolute path to program and add a #define for it
+AC_DEFUN([XPM_PATH_PROG],[
+AC_PATH_PROG([$1], [$2], [])
+AS_IF([test "x$$1" = "x"],
+ [AC_MSG_ERROR([$2 not found, set $1 or use --disable-stat-zfile])])
+AC_DEFINE_UNQUOTED([$1], ["$$1"], [Path to $2])
+]) dnl End of AC_DEFUN([XPM_PATH_PROG]...
+
# Optional feature: When a filename ending in .Z or .gz is requested,
# open a pipe to a newly forked compress/uncompress/gzip/gunzip command to
# handle it.
@@ -64,6 +72,12 @@ AC_ARG_ENABLE(open-zfile,
AC_MSG_RESULT([$OPEN_ZFILE])
if test x$OPEN_ZFILE = xno ; then
AC_DEFINE(NO_ZPIPE, 1, [Define to 1 to disable decompression via pipes])
+else
+ XPM_PATH_PROG([XPM_PATH_COMPRESS], [compress])
+ XPM_PATH_PROG([XPM_PATH_UNCOMPRESS], [uncompress])
+ XPM_PATH_PROG([XPM_PATH_GZIP], [gzip])
+ XPM_PATH_PROG([XPM_PATH_GUNZIP], [gunzip])
+ AC_CHECK_FUNCS([closefrom close_range], [break])
fi
# Optional feature: When ___.xpm is requested, also look for ___.xpm.Z & .gz
diff --git a/src/RdFToI.c b/src/RdFToI.c
index bd09611..a91d337 100644
--- a/src/RdFToI.c
+++ b/src/RdFToI.c
@@ -43,6 +43,7 @@
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include <unistd.h>
#else
#ifdef FOR_MSW
#include <fcntl.h>
@@ -161,7 +162,17 @@ xpmPipeThrough(
goto err;
if ( 0 == pid )
{
- execlp(cmd, cmd, arg1, (char *)NULL);
+#ifdef HAVE_CLOSEFROM
+ closefrom(3);
+#elif defined(HAVE_CLOSE_RANGE)
+# ifdef CLOSE_RANGE_UNSHARE
+# define close_range_flags CLOSE_RANGE_UNSHARE
+# else
+# define close_range_flags 0
+#endif
+ close_range(3, ~0U, close_range_flags);
+#endif
+ execl(cmd, cmd, arg1, (char *)NULL);
perror(cmd);
goto err;
}
@@ -235,12 +246,12 @@ OpenReadFile(
if ( ext && !strcmp(ext, ".Z") )
{
mdata->type = XPMPIPE;
- mdata->stream.file = xpmPipeThrough(fd, "uncompress", "-c", "r");
+ mdata->stream.file = xpmPipeThrough(fd, XPM_PATH_UNCOMPRESS, "-c", "r");
}
else if ( ext && !strcmp(ext, ".gz") )
{
mdata->type = XPMPIPE;
- mdata->stream.file = xpmPipeThrough(fd, "gunzip", "-qc", "r");
+ mdata->stream.file = xpmPipeThrough(fd, XPM_PATH_GUNZIP, "-qc", "r");
}
else
#endif /* z-files */
diff --git a/src/WrFFrI.c b/src/WrFFrI.c
index 328c987..d59098f 100644
--- a/src/WrFFrI.c
+++ b/src/WrFFrI.c
@@ -342,10 +342,10 @@ OpenWriteFile(
#ifndef NO_ZPIPE
len = strlen(filename);
if (len > 2 && !strcmp(".Z", filename + (len - 2))) {
- mdata->stream.file = xpmPipeThrough(fd, "compress", NULL, "w");
+ mdata->stream.file = xpmPipeThrough(fd, XPM_PATH_COMPRESS, NULL, "w");
mdata->type = XPMPIPE;
} else if (len > 3 && !strcmp(".gz", filename + (len - 3))) {
- mdata->stream.file = xpmPipeThrough(fd, "gzip", "-q", "w");
+ mdata->stream.file = xpmPipeThrough(fd, XPM_PATH_GZIP, "-q", "w");
mdata->type = XPMPIPE;
} else
#endif
--
2.27.0

View File

@ -1,68 +0,0 @@
From 8178eb0834d82242e1edbc7d4fb0d1b397569c68 Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
Date: Mon, 16 Jan 2023 19:44:52 +1000
Subject: [PATCH] Use gzip -d instead of gunzip
GNU gunzip [1] is a shell script that exec's `gzip -d`. Even if we call
/usr/bin/gunzip with the correct built-in path, the actual gzip call
will use whichever gzip it finds first, making our patch pointless.
Fix this by explicitly calling gzip -d instead.
https://git.savannah.gnu.org/cgit/gzip.git/tree/gunzip.in
[Part of the fix for CVE-2022-4883]
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
---
README.md | 2 +-
configure.ac | 3 +--
src/RdFToI.c | 2 +-
3 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/README.md b/README.md
index 30fdd8e..5410b82 100644
--- a/README.md
+++ b/README.md
@@ -41,5 +41,5 @@ the first version found in the PATH used to run configure, and do not depend
on the PATH environment variable set at runtime.
To specify paths to be used for these commands instead of searching $PATH, pass
-the XPM_PATH_COMPRESS, XPM_PATH_UNCOMPRESS, XPM_PATH_GZIP, and XPM_PATH_GUNZIP
+the XPM_PATH_COMPRESS, XPM_PATH_UNCOMPRESS, and XPM_PATH_GZIP
variables to the configure command.
diff --git a/configure.ac b/configure.ac
index e6b6509..6cd165f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -58,7 +58,7 @@ AC_DEFINE_UNQUOTED([$1], ["$$1"], [Path to $2])
]) dnl End of AC_DEFUN([XPM_PATH_PROG]...
# Optional feature: When a filename ending in .Z or .gz is requested,
-# open a pipe to a newly forked compress/uncompress/gzip/gunzip command to
+# open a pipe to a newly forked compress/uncompress/gzip command to
# handle it.
AC_MSG_CHECKING([whether to handle compressed pixmaps])
case $host_os in
@@ -77,7 +77,6 @@ else
XPM_PATH_PROG([XPM_PATH_COMPRESS], [compress])
XPM_PATH_PROG([XPM_PATH_UNCOMPRESS], [uncompress])
XPM_PATH_PROG([XPM_PATH_GZIP], [gzip])
- XPM_PATH_PROG([XPM_PATH_GUNZIP], [gunzip])
AC_CHECK_FUNCS([closefrom close_range], [break])
fi
diff --git a/src/RdFToI.c b/src/RdFToI.c
index a91d337..141c485 100644
--- a/src/RdFToI.c
+++ b/src/RdFToI.c
@@ -251,7 +251,7 @@ OpenReadFile(
else if ( ext && !strcmp(ext, ".gz") )
{
mdata->type = XPMPIPE;
- mdata->stream.file = xpmPipeThrough(fd, XPM_PATH_GUNZIP, "-qc", "r");
+ mdata->stream.file = xpmPipeThrough(fd, XPM_PATH_GZIP, "-dqc", "r");
}
else
#endif /* z-files */
--
GitLab

View File

@ -1,35 +0,0 @@
From a3a7c6dcc3b629d765014816c566c63165c63ca8 Mon Sep 17 00:00:00 2001
From: Alan Coopersmith <alan.coopersmith@oracle.com>
Date: Sat, 17 Dec 2022 12:23:45 -0800
Subject: [PATCH] Fix CVE-2022-46285: Infinite loop on unclosed comments
When reading XPM images from a file with libXpm 3.5.14 or older, if a
comment in the file is not closed (i.e. a C-style comment starts with
"/*" and is missing the closing "*/"), the ParseComment() function will
loop forever calling getc() to try to read the rest of the comment,
failing to notice that it has returned EOF, which may cause a denial of
service to the calling program.
Reported-by: Marco Ivaldi <raptor@0xdeadbeef.info>
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
---
src/data.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/data.c b/src/data.c
index 898889c..bfad4ff 100644
--- a/src/data.c
+++ b/src/data.c
@@ -174,6 +174,10 @@ ParseComment(xpmData *data)
notend = 0;
Ungetc(data, *s, file);
}
+ else if (c == EOF) {
+ /* hit end of file before the end of the comment */
+ return XpmFileInvalid;
+ }
}
return 0;
}
--
GitLab

Binary file not shown.

BIN
libXpm-3.5.15.tar.gz Normal file

Binary file not shown.

View File

@ -1,17 +1,10 @@
Name: libXpm
Version: 3.5.13
Release: 4
Version: 3.5.15
Release: 1
License: MIT
Summary: X.Org X11 libXpm runtime library
URL: https://www.x.org
Source0: https://www.x.org/pub/individual/lib/%{name}-%{version}.tar.bz2
Patch6000: backport-0001-CVE-2022-44617.patch
Patch6001: backport-0002-CVE-2022-44617.patch
Patch6002: backport-CVE-2022-46285.patch
Patch6003: backport-0001-CVE-2022-4883.patch
Patch6004: backport-0002-CVE-2022-4883.patch
Patch6005: backport-0003-CVE-2022-4883.patch
Source0: https://www.x.org/pub/individual/lib/%{name}-%{version}.tar.gz
BuildRequires: xorg-x11-util-macros autoconf automake libtool
BuildRequires: gettext libXau-devel libXext-devel libXt-devel
@ -59,10 +52,13 @@ autoreconf -ivf
%files help
%defattr(-,root,root)
%{_mandir}/man1/*.1*
%{_mandir}/man3/*.3*
%changelog
* Sat Feb 04 2023 zhouwenpei <zhouwenpei1@h-partners.com> - 3.5.15-1
- update to 3.5.15
* Wed Feb 01 2023 zhouwenpei <zhouwenpei1@h-partners.com> - 3.5.13-4
- fix CVE-2022-44617,CVE-2022-46285,CVE-2022-4883