untrusted comment: verify with openbsd-72-base.pub
RWQTKNnK3CZZ8KrtMDo8jQdPWyyyYcdhR9XRvy5x9Prv7T5RhHYgejQV5J2u0za8U0Ndc9koNw4+eH1SOeeP/JZ6TNkXr7lPnQI=

OpenBSD 7.2 errata 014, January 17, 2023

Input validation issues and path validation issues in libXpm can lead
to infinite loops, memory corruption or arbitrary command execution.
CVE-2022-46285, CVE-2022-44617 and CVE-2022-4883

Apply by doing:
    signify -Vep /etc/signify/openbsd-72-base.pub -x 014_libxpm.patch.sig \
        -m - | (cd /usr/xenocara && patch -p0)

And then compile and rebuild libXpm
    cd /usr/xenocara/lib/libXpm
    make -f Makefile.bsd-wrapper obj
    make -f Makefile.bsd-wrapper build

Index: lib/libXpm/Makefile.in
===================================================================
RCS file: /cvs/OpenBSD/xenocara/lib/libXpm/Makefile.in,v
diff -u -p -u -r1.10 Makefile.in
--- lib/libXpm/Makefile.in	4 Jan 2020 18:00:46 -0000	1.10
+++ lib/libXpm/Makefile.in	15 Jan 2023 18:04:18 -0000
@@ -268,6 +268,10 @@ VERSION = @VERSION@
 XORG_MAN_PAGE = @XORG_MAN_PAGE@
 XPM_CFLAGS = @XPM_CFLAGS@
 XPM_LIBS = @XPM_LIBS@
+XPM_PATH_COMPRESS = @XPM_PATH_COMPRESS@
+XPM_PATH_GUNZIP = @XPM_PATH_GUNZIP@
+XPM_PATH_GZIP = @XPM_PATH_GZIP@
+XPM_PATH_UNCOMPRESS = @XPM_PATH_UNCOMPRESS@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
 abs_top_builddir = @abs_top_builddir@
Index: lib/libXpm/config.h.in
===================================================================
RCS file: /cvs/OpenBSD/xenocara/lib/libXpm/config.h.in,v
diff -u -p -u -r1.5 config.h.in
--- lib/libXpm/config.h.in	28 Sep 2013 17:40:33 -0000	1.5
+++ lib/libXpm/config.h.in	15 Jan 2023 18:04:18 -0000
@@ -1,5 +1,11 @@
 /* config.h.in.  Generated from configure.ac by autoheader.  */
 
+/* Define to 1 if you have the `closefrom' function. */
+#undef HAVE_CLOSEFROM
+
+/* Define to 1 if you have the `close_range' function. */
+#undef HAVE_CLOSE_RANGE
+
 /* Define to 1 if you have the <dlfcn.h> header file. */
 #undef HAVE_DLFCN_H
 
@@ -73,9 +79,6 @@
 /* Patch version of this package */
 #undef PACKAGE_VERSION_PATCHLEVEL
 
-/* Define to 1 to automatically look for files with .Z & .gz extensions */
-#undef STAT_ZFILE
-
 /* Define to 1 if you have the ANSI C header files. */
 #undef STDC_HEADERS
 
@@ -84,3 +87,15 @@
 
 /* Version number of package */
 #undef VERSION
+
+/* Path to compress */
+#undef XPM_PATH_COMPRESS
+
+/* Path to gunzip */
+#undef XPM_PATH_GUNZIP
+
+/* Path to gzip */
+#undef XPM_PATH_GZIP
+
+/* Path to uncompress */
+#undef XPM_PATH_UNCOMPRESS
Index: lib/libXpm/configure
===================================================================
RCS file: /cvs/OpenBSD/xenocara/lib/libXpm/configure,v
diff -u -p -u -r1.16 configure
--- lib/libXpm/configure	4 Jan 2020 18:00:46 -0000	1.16
+++ lib/libXpm/configure	15 Jan 2023 18:04:18 -0000
@@ -637,6 +637,10 @@ ac_subst_vars='am__EXEEXT_FALSE
 am__EXEEXT_TRUE
 LTLIBOBJS
 LIBOBJS
+XPM_PATH_GUNZIP
+XPM_PATH_GZIP
+XPM_PATH_UNCOMPRESS
+XPM_PATH_COMPRESS
 USE_GETTEXT_FALSE
 USE_GETTEXT_TRUE
 LOCALEDIR
@@ -799,7 +803,6 @@ enable_selective_werror
 enable_strict_compilation
 enable_silent_rules
 with_localedir
-enable_stat_zfile
 '
       ac_precious_vars='build_alias
 host_alias
@@ -1455,8 +1458,6 @@ Optional Features:
                           errors (default: disabled)
   --enable-silent-rules   less verbose build output (undo: "make V=1")
   --disable-silent-rules  verbose build output (undo: "make V=0")
-  --enable-stat-zfile     Search for files with .Z & .gz extensions
-                          automatically [default=yes]
 
 Optional Packages:
   --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
@@ -17878,30 +17879,227 @@ else
 fi
 
 
-# Optional feature: When ___.xpm is requested, also look for ___.xpm.Z & .gz
-# Replaces ZFILEDEF = -DSTAT_ZFILE in old Imakefile
-# Check whether --enable-stat-zfile was given.
-if test "${enable_stat_zfile+set}" = set; then :
-  enableval=$enable_stat_zfile; STAT_ZFILE=$enableval
+
+case $host_os in
+        *mingw*)
+
+$as_echo "#define NO_ZPIPE 1" >>confdefs.h
+
+        ;;
+        *)
+
+# Extract the first word of "compress", so it can be a program name with args.
+set dummy compress; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_XPM_PATH_COMPRESS+:} false; then :
+  $as_echo_n "(cached) " >&6
 else
-  STAT_ZFILE=yes
+  case $XPM_PATH_COMPRESS in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_XPM_PATH_COMPRESS="$XPM_PATH_COMPRESS" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_XPM_PATH_COMPRESS="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
 fi
+XPM_PATH_COMPRESS=$ac_cv_path_XPM_PATH_COMPRESS
+if test -n "$XPM_PATH_COMPRESS"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XPM_PATH_COMPRESS" >&5
+$as_echo "$XPM_PATH_COMPRESS" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+if test "x$XPM_PATH_COMPRESS" = "x"; then :
+  as_fn_error $? "compress not found, set XPM_PATH_COMPRESS or use --disable-stat-zfile" "$LINENO" 5
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define XPM_PATH_COMPRESS "$XPM_PATH_COMPRESS"
+_ACEOF
 
-if test x$STAT_ZFILE = xyes ; then
 
-$as_echo "#define STAT_ZFILE 1" >>confdefs.h
 
+# Extract the first word of "uncompress", so it can be a program name with args.
+set dummy uncompress; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_XPM_PATH_UNCOMPRESS+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $XPM_PATH_UNCOMPRESS in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_XPM_PATH_UNCOMPRESS="$XPM_PATH_UNCOMPRESS" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_XPM_PATH_UNCOMPRESS="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+XPM_PATH_UNCOMPRESS=$ac_cv_path_XPM_PATH_UNCOMPRESS
+if test -n "$XPM_PATH_UNCOMPRESS"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XPM_PATH_UNCOMPRESS" >&5
+$as_echo "$XPM_PATH_UNCOMPRESS" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 fi
 
 
-case $host_os in
-	*mingw*)
+if test "x$XPM_PATH_UNCOMPRESS" = "x"; then :
+  as_fn_error $? "uncompress not found, set XPM_PATH_UNCOMPRESS or use --disable-stat-zfile" "$LINENO" 5
+fi
 
-$as_echo "#define NO_ZPIPE 1" >>confdefs.h
+cat >>confdefs.h <<_ACEOF
+#define XPM_PATH_UNCOMPRESS "$XPM_PATH_UNCOMPRESS"
+_ACEOF
 
-	;;
-	*)
-	;;
+
+
+# Extract the first word of "gzip", so it can be a program name with args.
+set dummy gzip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_XPM_PATH_GZIP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $XPM_PATH_GZIP in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_XPM_PATH_GZIP="$XPM_PATH_GZIP" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_XPM_PATH_GZIP="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+XPM_PATH_GZIP=$ac_cv_path_XPM_PATH_GZIP
+if test -n "$XPM_PATH_GZIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XPM_PATH_GZIP" >&5
+$as_echo "$XPM_PATH_GZIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+if test "x$XPM_PATH_GZIP" = "x"; then :
+  as_fn_error $? "gzip not found, set XPM_PATH_GZIP or use --disable-stat-zfile" "$LINENO" 5
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define XPM_PATH_GZIP "$XPM_PATH_GZIP"
+_ACEOF
+
+
+
+# Extract the first word of "gunzip", so it can be a program name with args.
+set dummy gunzip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_XPM_PATH_GUNZIP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $XPM_PATH_GUNZIP in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_XPM_PATH_GUNZIP="$XPM_PATH_GUNZIP" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_XPM_PATH_GUNZIP="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+XPM_PATH_GUNZIP=$ac_cv_path_XPM_PATH_GUNZIP
+if test -n "$XPM_PATH_GUNZIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XPM_PATH_GUNZIP" >&5
+$as_echo "$XPM_PATH_GUNZIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+if test "x$XPM_PATH_GUNZIP" = "x"; then :
+  as_fn_error $? "gunzip not found, set XPM_PATH_GUNZIP or use --disable-stat-zfile" "$LINENO" 5
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define XPM_PATH_GUNZIP "$XPM_PATH_GUNZIP"
+_ACEOF
+
+
+                for ac_func in closefrom close_range
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+ break
+fi
+done
+
+        ;;
 esac
 
 ac_config_files="$ac_config_files Makefile doc/Makefile include/Makefile man/Makefile src/Makefile sxpm/Makefile cxpm/Makefile xpm.pc"
Index: lib/libXpm/configure.ac
===================================================================
RCS file: /cvs/OpenBSD/xenocara/lib/libXpm/configure.ac,v
diff -u -p -u -r1.7 configure.ac
--- lib/libXpm/configure.ac	4 Jan 2020 18:00:46 -0000	1.7
+++ lib/libXpm/configure.ac	15 Jan 2023 18:04:18 -0000
@@ -49,23 +49,25 @@ if test "x$USE_GETTEXT" = "xyes" ; then
 fi
 AM_CONDITIONAL(USE_GETTEXT, test "x$USE_GETTEXT" = "xyes")
 
-# Optional feature: When ___.xpm is requested, also look for ___.xpm.Z & .gz
-# Replaces ZFILEDEF = -DSTAT_ZFILE in old Imakefile
-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])
-if test x$STAT_ZFILE = xyes ; then
-	AC_DEFINE(STAT_ZFILE, 1, [Define to 1 to automatically look for files with .Z & .gz extensions])
-fi
-
+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]...
 
 case $host_os in
-	*mingw*)
+        *mingw*)
                 AC_DEFINE(NO_ZPIPE, 1, [Define to 1 to disable decompression via pipes])
-	;;
-	*)
-	;;
+        ;;
+        *)
+                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])
+        ;;
 esac
 
 AC_CONFIG_FILES([Makefile
Index: lib/libXpm/cxpm/Makefile.in
===================================================================
RCS file: /cvs/OpenBSD/xenocara/lib/libXpm/cxpm/Makefile.in,v
diff -u -p -u -r1.8 Makefile.in
--- lib/libXpm/cxpm/Makefile.in	11 Oct 2016 22:15:33 -0000	1.8
+++ lib/libXpm/cxpm/Makefile.in	15 Jan 2023 18:04:18 -0000
@@ -210,6 +210,10 @@ VERSION = @VERSION@
 XORG_MAN_PAGE = @XORG_MAN_PAGE@
 XPM_CFLAGS = @XPM_CFLAGS@
 XPM_LIBS = @XPM_LIBS@
+XPM_PATH_COMPRESS = @XPM_PATH_COMPRESS@
+XPM_PATH_GUNZIP = @XPM_PATH_GUNZIP@
+XPM_PATH_GZIP = @XPM_PATH_GZIP@
+XPM_PATH_UNCOMPRESS = @XPM_PATH_UNCOMPRESS@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
 abs_top_builddir = @abs_top_builddir@
Index: lib/libXpm/doc/Makefile.in
===================================================================
RCS file: /cvs/OpenBSD/xenocara/lib/libXpm/doc/Makefile.in,v
diff -u -p -u -r1.4 Makefile.in
--- lib/libXpm/doc/Makefile.in	11 Oct 2016 22:15:33 -0000	1.4
+++ lib/libXpm/doc/Makefile.in	15 Jan 2023 18:04:18 -0000
@@ -172,6 +172,10 @@ VERSION = @VERSION@
 XORG_MAN_PAGE = @XORG_MAN_PAGE@
 XPM_CFLAGS = @XPM_CFLAGS@
 XPM_LIBS = @XPM_LIBS@
+XPM_PATH_COMPRESS = @XPM_PATH_COMPRESS@
+XPM_PATH_GUNZIP = @XPM_PATH_GUNZIP@
+XPM_PATH_GZIP = @XPM_PATH_GZIP@
+XPM_PATH_UNCOMPRESS = @XPM_PATH_UNCOMPRESS@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
 abs_top_builddir = @abs_top_builddir@
Index: lib/libXpm/include/Makefile.in
===================================================================
RCS file: /cvs/OpenBSD/xenocara/lib/libXpm/include/Makefile.in,v
diff -u -p -u -r1.5 Makefile.in
--- lib/libXpm/include/Makefile.in	11 Oct 2016 22:15:33 -0000	1.5
+++ lib/libXpm/include/Makefile.in	15 Jan 2023 18:04:18 -0000
@@ -205,6 +205,10 @@ VERSION = @VERSION@
 XORG_MAN_PAGE = @XORG_MAN_PAGE@
 XPM_CFLAGS = @XPM_CFLAGS@
 XPM_LIBS = @XPM_LIBS@
+XPM_PATH_COMPRESS = @XPM_PATH_COMPRESS@
+XPM_PATH_GUNZIP = @XPM_PATH_GUNZIP@
+XPM_PATH_GZIP = @XPM_PATH_GZIP@
+XPM_PATH_UNCOMPRESS = @XPM_PATH_UNCOMPRESS@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
 abs_top_builddir = @abs_top_builddir@
Index: lib/libXpm/man/Makefile.in
===================================================================
RCS file: /cvs/OpenBSD/xenocara/lib/libXpm/man/Makefile.in,v
diff -u -p -u -r1.3 Makefile.in
--- lib/libXpm/man/Makefile.in	11 Oct 2016 22:15:33 -0000	1.3
+++ lib/libXpm/man/Makefile.in	15 Jan 2023 18:04:18 -0000
@@ -225,6 +225,10 @@ VERSION = @VERSION@
 XORG_MAN_PAGE = @XORG_MAN_PAGE@
 XPM_CFLAGS = @XPM_CFLAGS@
 XPM_LIBS = @XPM_LIBS@
+XPM_PATH_COMPRESS = @XPM_PATH_COMPRESS@
+XPM_PATH_GUNZIP = @XPM_PATH_GUNZIP@
+XPM_PATH_GZIP = @XPM_PATH_GZIP@
+XPM_PATH_UNCOMPRESS = @XPM_PATH_UNCOMPRESS@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
 abs_top_builddir = @abs_top_builddir@
Index: lib/libXpm/src/Makefile.in
===================================================================
RCS file: /cvs/OpenBSD/xenocara/lib/libXpm/src/Makefile.in,v
diff -u -p -u -r1.8 Makefile.in
--- lib/libXpm/src/Makefile.in	11 Oct 2016 22:15:33 -0000	1.8
+++ lib/libXpm/src/Makefile.in	15 Jan 2023 18:04:18 -0000
@@ -245,6 +245,10 @@ VERSION = @VERSION@
 XORG_MAN_PAGE = @XORG_MAN_PAGE@
 XPM_CFLAGS = @XPM_CFLAGS@
 XPM_LIBS = @XPM_LIBS@
+XPM_PATH_COMPRESS = @XPM_PATH_COMPRESS@
+XPM_PATH_GUNZIP = @XPM_PATH_GUNZIP@
+XPM_PATH_GZIP = @XPM_PATH_GZIP@
+XPM_PATH_UNCOMPRESS = @XPM_PATH_UNCOMPRESS@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
 abs_top_builddir = @abs_top_builddir@
Index: lib/libXpm/src/RdFToI.c
===================================================================
RCS file: /cvs/OpenBSD/xenocara/lib/libXpm/src/RdFToI.c,v
diff -u -p -u -r1.4 RdFToI.c
--- lib/libXpm/src/RdFToI.c	28 Sep 2013 17:40:35 -0000	1.4
+++ lib/libXpm/src/RdFToI.c	15 Jan 2023 18:04:18 -0000
@@ -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 */
Index: lib/libXpm/src/WrFFrI.c
===================================================================
RCS file: /cvs/OpenBSD/xenocara/lib/libXpm/src/WrFFrI.c,v
diff -u -p -u -r1.6 WrFFrI.c
--- lib/libXpm/src/WrFFrI.c	4 Jan 2020 18:00:46 -0000	1.6
+++ lib/libXpm/src/WrFFrI.c	15 Jan 2023 18:04:18 -0000
@@ -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
Index: lib/libXpm/src/create.c
===================================================================
RCS file: /cvs/OpenBSD/xenocara/lib/libXpm/src/create.c,v
diff -u -p -u -r1.5 create.c
--- lib/libXpm/src/create.c	16 Dec 2016 07:28:34 -0000	1.5
+++ lib/libXpm/src/create.c	15 Jan 2023 18:04:18 -0000
@@ -994,6 +994,7 @@ 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 */
Index: lib/libXpm/src/data.c
===================================================================
RCS file: /cvs/OpenBSD/xenocara/lib/libXpm/src/data.c,v
diff -u -p -u -r1.4 data.c
--- lib/libXpm/src/data.c	10 Mar 2012 14:30:33 -0000	1.4
+++ lib/libXpm/src/data.c	15 Jan 2023 18:04:18 -0000
@@ -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;
     }
@@ -191,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--;
 	}
@@ -212,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
@@ -230,7 +242,7 @@ xpmNextString(xpmData *data)
 	    Ungetc(data, c, file);
 	}
     }
-    return 0;
+    return XpmSuccess;
 }
 
 
Index: lib/libXpm/src/parse.c
===================================================================
RCS file: /cvs/OpenBSD/xenocara/lib/libXpm/src/parse.c,v
diff -u -p -u -r1.6 parse.c
--- lib/libXpm/src/parse.c	4 Jan 2020 18:00:46 -0000	1.6
+++ lib/libXpm/src/parse.c	15 Jan 2023 18:04:18 -0000
@@ -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);
Index: lib/libXpm/sxpm/Makefile.in
===================================================================
RCS file: /cvs/OpenBSD/xenocara/lib/libXpm/sxpm/Makefile.in,v
diff -u -p -u -r1.8 Makefile.in
--- lib/libXpm/sxpm/Makefile.in	11 Oct 2016 22:15:33 -0000	1.8
+++ lib/libXpm/sxpm/Makefile.in	15 Jan 2023 18:04:18 -0000
@@ -214,6 +214,10 @@ VERSION = @VERSION@
 XORG_MAN_PAGE = @XORG_MAN_PAGE@
 XPM_CFLAGS = @XPM_CFLAGS@
 XPM_LIBS = @XPM_LIBS@
+XPM_PATH_COMPRESS = @XPM_PATH_COMPRESS@
+XPM_PATH_GUNZIP = @XPM_PATH_GUNZIP@
+XPM_PATH_GZIP = @XPM_PATH_GZIP@
+XPM_PATH_UNCOMPRESS = @XPM_PATH_UNCOMPRESS@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
 abs_top_builddir = @abs_top_builddir@
