diff mbox series

zlib: Fix CVE-2026-22184

Message ID 20260119081635.3976267-1-mingli.yu@windriver.com
State New
Headers show
Series zlib: Fix CVE-2026-22184 | expand

Commit Message

Yu, Mingli Jan. 19, 2026, 8:16 a.m. UTC
From: Mingli Yu <mingli.yu@windriver.com>

Backport a patch [1] to fix CVE-2026-22184.

[1] https://github.com/madler/zlib/commit/1a40058a92d525aa49a6eac698cfde500fc9b92f

Signed-off-by: Mingli Yu <mingli.yu@windriver.com>
---
 .../zlib/zlib/CVE-2026-22184.patch            | 753 ++++++++++++++++++
 meta/recipes-core/zlib/zlib_1.3.1.bb          |   1 +
 2 files changed, 754 insertions(+)
 create mode 100644 meta/recipes-core/zlib/zlib/CVE-2026-22184.patch

Comments

Marko, Peter Jan. 19, 2026, 8:58 a.m. UTC | #1
Not sure which one is nicer for this useless CVE.
Removing related files as this patch or setting CVE_STATUS as in https://lists.openembedded.org/g/openembedded-core/message/229564
Let the maintainers decide...

Peter

> -----Original Message-----
> From: openembedded-core@lists.openembedded.org <openembedded-
> core@lists.openembedded.org> On Behalf Of Yu, Mingli via
> lists.openembedded.org
> Sent: Monday, January 19, 2026 9:17
> To: openembedded-core@lists.openembedded.org
> Subject: [OE-core] [PATCH] zlib: Fix CVE-2026-22184
> 
> From: Mingli Yu <mingli.yu@windriver.com>
> 
> Backport a patch [1] to fix CVE-2026-22184.
> 
> [1]
> https://github.com/madler/zlib/commit/1a40058a92d525aa49a6eac698cfde500fc9b
> 92f
> 
> Signed-off-by: Mingli Yu <mingli.yu@windriver.com>
> ---
>  .../zlib/zlib/CVE-2026-22184.patch            | 753 ++++++++++++++++++
>  meta/recipes-core/zlib/zlib_1.3.1.bb          |   1 +
>  2 files changed, 754 insertions(+)
>  create mode 100644 meta/recipes-core/zlib/zlib/CVE-2026-22184.patch
> 
> diff --git a/meta/recipes-core/zlib/zlib/CVE-2026-22184.patch b/meta/recipes-
> core/zlib/zlib/CVE-2026-22184.patch
> new file mode 100644
> index 0000000000..130195d1ff
> --- /dev/null
> +++ b/meta/recipes-core/zlib/zlib/CVE-2026-22184.patch
> @@ -0,0 +1,753 @@
> +From 1a40058a92d525aa49a6eac698cfde500fc9b92f Mon Sep 17 00:00:00 2001
> +From: Mark Adler <git@madler.net>
> +Date: Sun, 11 Jan 2026 13:00:25 -0800
> +Subject: [PATCH] Remove untgz from contrib.
> +
> +CVE: CVE-2026-22184
> +
> +Upstream-Status: Backport
> [https://github.com/madler/zlib/commit/1a40058a92d525aa49a6eac698cfde500fc9b
> 92f]
> +
> +Signed-off-by: Mingli Yu <mingli.yu@windriver.com>
> +---
> + contrib/README.contrib     |   3 -
> + contrib/untgz/Makefile     |  14 -
> + contrib/untgz/Makefile.msc |  17 -
> + contrib/untgz/untgz.c      | 667 -------------------------------------
> + 4 files changed, 701 deletions(-)
> + delete mode 100644 contrib/untgz/Makefile
> + delete mode 100644 contrib/untgz/Makefile.msc
> + delete mode 100644 contrib/untgz/untgz.c
> +
> +diff --git a/contrib/README.contrib b/contrib/README.contrib
> +index 5e5f950..d9480ee 100644
> +--- a/contrib/README.contrib
> ++++ b/contrib/README.contrib
> +@@ -49,9 +49,6 @@ puff/       by Mark Adler <madler@alumni.caltech.edu>
> + testzlib/   by Gilles Vollant <info@winimage.com>
> +         Example of the use of zlib
> +
> +-untgz/      by Pedro A. Aranda Gutierrez <paag@tid.es>
> +-        A very simple tar.gz file extractor using zlib
> +-
> + vstudio/    by Gilles Vollant <info@winimage.com>
> +         Building a minizip-enhanced zlib with Microsoft Visual Studio
> +         Includes vc11 from kreuzerkrieg and vc12 from davispuh
> +diff --git a/contrib/untgz/Makefile b/contrib/untgz/Makefile
> +deleted file mode 100644
> +index b54266f..0000000
> +--- a/contrib/untgz/Makefile
> ++++ /dev/null
> +@@ -1,14 +0,0 @@
> +-CC=cc
> +-CFLAGS=-g
> +-
> +-untgz: untgz.o ../../libz.a
> +-	$(CC) $(CFLAGS) -o untgz untgz.o -L../.. -lz
> +-
> +-untgz.o: untgz.c ../../zlib.h
> +-	$(CC) $(CFLAGS) -c -I../.. untgz.c
> +-
> +-../../libz.a:
> +-	cd ../..; ./configure; make
> +-
> +-clean:
> +-	rm -f untgz untgz.o *~
> +diff --git a/contrib/untgz/Makefile.msc b/contrib/untgz/Makefile.msc
> +deleted file mode 100644
> +index 77b8602..0000000
> +--- a/contrib/untgz/Makefile.msc
> ++++ /dev/null
> +@@ -1,17 +0,0 @@
> +-CC=cl
> +-CFLAGS=-MD
> +-
> +-untgz.exe: untgz.obj ..\..\zlib.lib
> +-	$(CC) $(CFLAGS) untgz.obj ..\..\zlib.lib
> +-
> +-untgz.obj: untgz.c ..\..\zlib.h
> +-	$(CC) $(CFLAGS) -c -I..\.. untgz.c
> +-
> +-..\..\zlib.lib:
> +-	cd ..\..
> +-	$(MAKE) -f win32\makefile.msc
> +-	cd contrib\untgz
> +-
> +-clean:
> +-	-del untgz.obj
> +-	-del untgz.exe
> +diff --git a/contrib/untgz/untgz.c b/contrib/untgz/untgz.c
> +deleted file mode 100644
> +index 7857921..0000000
> +--- a/contrib/untgz/untgz.c
> ++++ /dev/null
> +@@ -1,667 +0,0 @@
> +-/*
> +- * untgz.c -- Display contents and extract files from a gzip'd TAR file
> +- *
> +- * written by Pedro A. Aranda Gutierrez <paag@tid.es>
> +- * adaptation to Unix by Jean-loup Gailly <jloup@gzip.org>
> +- * various fixes by Cosmin Truta <cosmint@cs.ubbcluj.ro>
> +- *
> +- * This software is provided 'as-is', without any express or implied
> +- * warranty.  In no event will the authors be held liable for any damages
> +- * arising from the use of this software.
> +- *
> +- * Permission is granted to anyone to use this software for any purpose,
> +- * including commercial applications, and to alter it and redistribute it
> +- * freely, subject to the following restrictions:
> +- *
> +- * 1. The origin of this software must not be misrepresented; you must not
> +- *    claim that you wrote the original software. If you use this software
> +- *    in a product, an acknowledgment in the product documentation would be
> +- *    appreciated but is not required.
> +- * 2. Altered source versions must be plainly marked as such, and must not be
> +- *    misrepresented as being the original software.
> +- * 3. This notice may not be removed or altered from any source distribution.
> +- */
> +-
> +-#include <stdio.h>
> +-#include <stdlib.h>
> +-#include <string.h>
> +-#include <time.h>
> +-#include <errno.h>
> +-
> +-#include "zlib.h"
> +-
> +-#ifdef _WIN32
> +-#  include <direct.h>
> +-#  include <io.h>
> +-#  include <windows.h>
> +-#  ifndef F_OK
> +-#    define F_OK  0
> +-#  endif
> +-#  define mkdir(dirname,mode)   _mkdir(dirname)
> +-#  ifdef _MSC_VER
> +-#    define access(path,mode)   _access(path,mode)
> +-#    define chmod(path,mode)    _chmod(path,mode)
> +-#    define strdup(str)         _strdup(str)
> +-#  endif
> +-#else
> +-#  include <sys/stat.h>
> +-#  include <unistd.h>
> +-#  include <utime.h>
> +-#endif
> +-
> +-
> +-/* values used in typeflag field */
> +-
> +-#define REGTYPE  '0'            /* regular file */
> +-#define AREGTYPE '\0'           /* regular file */
> +-#define LNKTYPE  '1'            /* link */
> +-#define SYMTYPE  '2'            /* reserved */
> +-#define CHRTYPE  '3'            /* character special */
> +-#define BLKTYPE  '4'            /* block special */
> +-#define DIRTYPE  '5'            /* directory */
> +-#define FIFOTYPE '6'            /* FIFO special */
> +-#define CONTTYPE '7'            /* reserved */
> +-
> +-/* GNU tar extensions */
> +-
> +-#define GNUTYPE_DUMPDIR  'D'    /* file names from dumped directory */
> +-#define GNUTYPE_LONGLINK 'K'    /* long link name */
> +-#define GNUTYPE_LONGNAME 'L'    /* long file name */
> +-#define GNUTYPE_MULTIVOL 'M'    /* continuation of file from another volume */
> +-#define GNUTYPE_NAMES    'N'    /* file name that does not fit into main hdr */
> +-#define GNUTYPE_SPARSE   'S'    /* sparse file */
> +-#define GNUTYPE_VOLHDR   'V'    /* tape/volume header */
> +-
> +-
> +-/* tar header */
> +-
> +-#define BLOCKSIZE     512
> +-#define SHORTNAMESIZE 100
> +-
> +-struct tar_header
> +-{                               /* byte offset */
> +-  char name[100];               /*   0 */
> +-  char mode[8];                 /* 100 */
> +-  char uid[8];                  /* 108 */
> +-  char gid[8];                  /* 116 */
> +-  char size[12];                /* 124 */
> +-  char mtime[12];               /* 136 */
> +-  char chksum[8];               /* 148 */
> +-  char typeflag;                /* 156 */
> +-  char linkname[100];           /* 157 */
> +-  char magic[6];                /* 257 */
> +-  char version[2];              /* 263 */
> +-  char uname[32];               /* 265 */
> +-  char gname[32];               /* 297 */
> +-  char devmajor[8];             /* 329 */
> +-  char devminor[8];             /* 337 */
> +-  char prefix[155];             /* 345 */
> +-                                /* 500 */
> +-};
> +-
> +-union tar_buffer
> +-{
> +-  char               buffer[BLOCKSIZE];
> +-  struct tar_header  header;
> +-};
> +-
> +-struct attr_item
> +-{
> +-  struct attr_item  *next;
> +-  char              *fname;
> +-  int                mode;
> +-  time_t             time;
> +-};
> +-
> +-enum { TGZ_EXTRACT, TGZ_LIST, TGZ_INVALID };
> +-
> +-char *prog;
> +-
> +-void error(const char *msg)
> +-{
> +-  fprintf(stderr, "%s: %s\n", prog, msg);
> +-  exit(1);
> +-}
> +-
> +-const char *TGZsuffix[] = { "\0", ".tar", ".tar.gz", ".taz", ".tgz", NULL };
> +-
> +-/* return the file name of the TGZ archive */
> +-/* or NULL if it does not exist */
> +-
> +-char *TGZfname (const char *arcname)
> +-{
> +-  static char buffer[1024];
> +-  int origlen,i;
> +-
> +-  strcpy(buffer,arcname);
> +-  origlen = strlen(buffer);
> +-
> +-  for (i=0; TGZsuffix[i]; i++)
> +-    {
> +-       strcpy(buffer+origlen,TGZsuffix[i]);
> +-       if (access(buffer,F_OK) == 0)
> +-         return buffer;
> +-    }
> +-  return NULL;
> +-}
> +-
> +-
> +-/* error message for the filename */
> +-
> +-void TGZnotfound (const char *arcname)
> +-{
> +-  int i;
> +-
> +-  fprintf(stderr,"%s: Couldn't find ",prog);
> +-  for (i=0;TGZsuffix[i];i++)
> +-    fprintf(stderr,(TGZsuffix[i+1]) ? "%s%s, " : "or %s%s\n",
> +-            arcname,
> +-            TGZsuffix[i]);
> +-  exit(1);
> +-}
> +-
> +-
> +-/* convert octal digits to int */
> +-/* on error return -1 */
> +-
> +-int getoct (char *p,int width)
> +-{
> +-  int result = 0;
> +-  char c;
> +-
> +-  while (width--)
> +-    {
> +-      c = *p++;
> +-      if (c == 0)
> +-        break;
> +-      if (c == ' ')
> +-        continue;
> +-      if (c < '0' || c > '7')
> +-        return -1;
> +-      result = result * 8 + (c - '0');
> +-    }
> +-  return result;
> +-}
> +-
> +-
> +-/* convert time_t to string */
> +-/* use the "YYYY/MM/DD hh:mm:ss" format */
> +-
> +-char *strtime (time_t *t)
> +-{
> +-  struct tm   *local;
> +-  static char result[32];
> +-
> +-  local = localtime(t);
> +-  sprintf(result,"%4d/%02d/%02d %02d:%02d:%02d",
> +-          local->tm_year+1900, local->tm_mon+1, local->tm_mday,
> +-          local->tm_hour, local->tm_min, local->tm_sec);
> +-  return result;
> +-}
> +-
> +-
> +-/* set file time */
> +-
> +-int setfiletime (char *fname,time_t ftime)
> +-{
> +-#ifdef _WIN32
> +-  static int isWinNT = -1;
> +-  SYSTEMTIME st;
> +-  FILETIME locft, modft;
> +-  struct tm *loctm;
> +-  HANDLE hFile;
> +-  int result;
> +-
> +-  loctm = localtime(&ftime);
> +-  if (loctm == NULL)
> +-    return -1;
> +-
> +-  st.wYear         = (WORD)loctm->tm_year + 1900;
> +-  st.wMonth        = (WORD)loctm->tm_mon + 1;
> +-  st.wDayOfWeek    = (WORD)loctm->tm_wday;
> +-  st.wDay          = (WORD)loctm->tm_mday;
> +-  st.wHour         = (WORD)loctm->tm_hour;
> +-  st.wMinute       = (WORD)loctm->tm_min;
> +-  st.wSecond       = (WORD)loctm->tm_sec;
> +-  st.wMilliseconds = 0;
> +-  if (!SystemTimeToFileTime(&st, &locft) ||
> +-      !LocalFileTimeToFileTime(&locft, &modft))
> +-    return -1;
> +-
> +-  if (isWinNT < 0)
> +-    isWinNT = (GetVersion() < 0x80000000) ? 1 : 0;
> +-  hFile = CreateFile(fname, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
> +-                     (isWinNT ? FILE_FLAG_BACKUP_SEMANTICS : 0),
> +-                     NULL);
> +-  if (hFile == INVALID_HANDLE_VALUE)
> +-    return -1;
> +-  result = SetFileTime(hFile, NULL, NULL, &modft) ? 0 : -1;
> +-  CloseHandle(hFile);
> +-  return result;
> +-#else
> +-  struct utimbuf settime;
> +-
> +-  settime.actime = settime.modtime = ftime;
> +-  return utime(fname,&settime);
> +-#endif
> +-}
> +-
> +-
> +-/* push file attributes */
> +-
> +-void push_attr(struct attr_item **list,char *fname,int mode,time_t time)
> +-{
> +-  struct attr_item *item;
> +-
> +-  item = (struct attr_item *)malloc(sizeof(struct attr_item));
> +-  if (item == NULL)
> +-    error("Out of memory");
> +-  item->fname = strdup(fname);
> +-  item->mode  = mode;
> +-  item->time  = time;
> +-  item->next  = *list;
> +-  *list       = item;
> +-}
> +-
> +-
> +-/* restore file attributes */
> +-
> +-void restore_attr(struct attr_item **list)
> +-{
> +-  struct attr_item *item, *prev;
> +-
> +-  for (item = *list; item != NULL; )
> +-    {
> +-      setfiletime(item->fname,item->time);
> +-      chmod(item->fname,item->mode);
> +-      prev = item;
> +-      item = item->next;
> +-      free(prev);
> +-    }
> +-  *list = NULL;
> +-}
> +-
> +-
> +-/* match regular expression */
> +-
> +-#define ISSPECIAL(c) (((c) == '*') || ((c) == '/'))
> +-
> +-int ExprMatch (char *string,char *expr)
> +-{
> +-  while (1)
> +-    {
> +-      if (ISSPECIAL(*expr))
> +-        {
> +-          if (*expr == '/')
> +-            {
> +-              if (*string != '\\' && *string != '/')
> +-                return 0;
> +-              string ++; expr++;
> +-            }
> +-          else if (*expr == '*')
> +-            {
> +-              if (*expr ++ == 0)
> +-                return 1;
> +-              while (*++string != *expr)
> +-                if (*string == 0)
> +-                  return 0;
> +-            }
> +-        }
> +-      else
> +-        {
> +-          if (*string != *expr)
> +-            return 0;
> +-          if (*expr++ == 0)
> +-            return 1;
> +-          string++;
> +-        }
> +-    }
> +-}
> +-
> +-
> +-/* recursive mkdir */
> +-/* abort on ENOENT; ignore other errors like "directory already exists" */
> +-/* return 1 if OK */
> +-/*        0 on error */
> +-
> +-int makedir (char *newdir)
> +-{
> +-  char *buffer = strdup(newdir);
> +-  char *p;
> +-  int  len = strlen(buffer);
> +-
> +-  if (len <= 0) {
> +-    free(buffer);
> +-    return 0;
> +-  }
> +-  if (buffer[len-1] == '/') {
> +-    buffer[len-1] = '\0';
> +-  }
> +-  if (mkdir(buffer, 0755) == 0)
> +-    {
> +-      free(buffer);
> +-      return 1;
> +-    }
> +-
> +-  p = buffer+1;
> +-  while (1)
> +-    {
> +-      char hold;
> +-
> +-      while(*p && *p != '\\' && *p != '/')
> +-        p++;
> +-      hold = *p;
> +-      *p = 0;
> +-      if ((mkdir(buffer, 0755) == -1) && (errno == ENOENT))
> +-        {
> +-          fprintf(stderr,"%s: Couldn't create directory %s\n",prog,buffer);
> +-          free(buffer);
> +-          return 0;
> +-        }
> +-      if (hold == 0)
> +-        break;
> +-      *p++ = hold;
> +-    }
> +-  free(buffer);
> +-  return 1;
> +-}
> +-
> +-
> +-int matchname (int arg,int argc,char **argv,char *fname)
> +-{
> +-  if (arg == argc)      /* no arguments given (untgz tgzarchive) */
> +-    return 1;
> +-
> +-  while (arg < argc)
> +-    if (ExprMatch(fname,argv[arg++]))
> +-      return 1;
> +-
> +-  return 0; /* ignore this for the moment being */
> +-}
> +-
> +-
> +-/* tar file list or extract */
> +-
> +-int tar (gzFile in,int action,int arg,int argc,char **argv)
> +-{
> +-  union  tar_buffer buffer;
> +-  int    len;
> +-  int    err;
> +-  int    getheader = 1;
> +-  int    remaining = 0;
> +-  FILE   *outfile = NULL;
> +-  char   fname[BLOCKSIZE];
> +-  int    tarmode;
> +-  time_t tartime;
> +-  struct attr_item *attributes = NULL;
> +-
> +-  if (action == TGZ_LIST)
> +-    printf("    date      time     size                       file\n"
> +-           " ---------- -------- --------- -------------------------------------\n");
> +-  while (1)
> +-    {
> +-      len = gzread(in, &buffer, BLOCKSIZE);
> +-      if (len < 0)
> +-        error(gzerror(in, &err));
> +-      /*
> +-       * Always expect complete blocks to process
> +-       * the tar information.
> +-       */
> +-      if (len != BLOCKSIZE)
> +-        {
> +-          action = TGZ_INVALID; /* force error exit */
> +-          remaining = 0;        /* force I/O cleanup */
> +-        }
> +-
> +-      /*
> +-       * If we have to get a tar header
> +-       */
> +-      if (getheader >= 1)
> +-        {
> +-          /*
> +-           * if we met the end of the tar
> +-           * or the end-of-tar block,
> +-           * we are done
> +-           */
> +-          if (len == 0 || buffer.header.name[0] == 0)
> +-            break;
> +-
> +-          tarmode = getoct(buffer.header.mode,8);
> +-          tartime = (time_t)getoct(buffer.header.mtime,12);
> +-          if (tarmode == -1 || tartime == (time_t)-1)
> +-            {
> +-              buffer.header.name[0] = 0;
> +-              action = TGZ_INVALID;
> +-            }
> +-
> +-          if (getheader == 1)
> +-            {
> +-              strncpy(fname,buffer.header.name,SHORTNAMESIZE);
> +-              if (fname[SHORTNAMESIZE-1] != 0)
> +-                  fname[SHORTNAMESIZE] = 0;
> +-            }
> +-          else
> +-            {
> +-              /*
> +-               * The file name is longer than SHORTNAMESIZE
> +-               */
> +-              if (strncmp(fname,buffer.header.name,SHORTNAMESIZE-1) != 0)
> +-                  error("bad long name");
> +-              getheader = 1;
> +-            }
> +-
> +-          /*
> +-           * Act according to the type flag
> +-           */
> +-          switch (buffer.header.typeflag)
> +-            {
> +-            case DIRTYPE:
> +-              if (action == TGZ_LIST)
> +-                printf(" %s     <dir> %s\n",strtime(&tartime),fname);
> +-              if (action == TGZ_EXTRACT)
> +-                {
> +-                  makedir(fname);
> +-                  push_attr(&attributes,fname,tarmode,tartime);
> +-                }
> +-              break;
> +-            case REGTYPE:
> +-            case AREGTYPE:
> +-              remaining = getoct(buffer.header.size,12);
> +-              if (remaining == -1)
> +-                {
> +-                  action = TGZ_INVALID;
> +-                  break;
> +-                }
> +-              if (action == TGZ_LIST)
> +-                printf(" %s %9d %s\n",strtime(&tartime),remaining,fname);
> +-              else if (action == TGZ_EXTRACT)
> +-                {
> +-                  if (matchname(arg,argc,argv,fname))
> +-                    {
> +-                      outfile = fopen(fname,"wb");
> +-                      if (outfile == NULL) {
> +-                        /* try creating directory */
> +-                        char *p = strrchr(fname, '/');
> +-                        if (p != NULL) {
> +-                          *p = '\0';
> +-                          makedir(fname);
> +-                          *p = '/';
> +-                          outfile = fopen(fname,"wb");
> +-                        }
> +-                      }
> +-                      if (outfile != NULL)
> +-                        printf("Extracting %s\n",fname);
> +-                      else
> +-                        fprintf(stderr, "%s: Couldn't create %s",prog,fname);
> +-                    }
> +-                  else
> +-                    outfile = NULL;
> +-                }
> +-              getheader = 0;
> +-              break;
> +-            case GNUTYPE_LONGLINK:
> +-            case GNUTYPE_LONGNAME:
> +-              remaining = getoct(buffer.header.size,12);
> +-              if (remaining < 0 || remaining >= BLOCKSIZE)
> +-                {
> +-                  action = TGZ_INVALID;
> +-                  break;
> +-                }
> +-              len = gzread(in, fname, BLOCKSIZE);
> +-              if (len < 0)
> +-                error(gzerror(in, &err));
> +-              if (fname[BLOCKSIZE-1] != 0 || (int)strlen(fname) > remaining)
> +-                {
> +-                  action = TGZ_INVALID;
> +-                  break;
> +-                }
> +-              getheader = 2;
> +-              break;
> +-            default:
> +-              if (action == TGZ_LIST)
> +-                printf(" %s     <---> %s\n",strtime(&tartime),fname);
> +-              break;
> +-            }
> +-        }
> +-      else
> +-        {
> +-          unsigned int bytes = (remaining > BLOCKSIZE) ? BLOCKSIZE : remaining;
> +-
> +-          if (outfile != NULL)
> +-            {
> +-              if (fwrite(&buffer,sizeof(char),bytes,outfile) != bytes)
> +-                {
> +-                  fprintf(stderr,
> +-                    "%s: Error writing %s -- skipping\n",prog,fname);
> +-                  fclose(outfile);
> +-                  outfile = NULL;
> +-                  remove(fname);
> +-                }
> +-            }
> +-          remaining -= bytes;
> +-        }
> +-
> +-      if (remaining == 0)
> +-        {
> +-          getheader = 1;
> +-          if (outfile != NULL)
> +-            {
> +-              fclose(outfile);
> +-              outfile = NULL;
> +-              if (action != TGZ_INVALID)
> +-                push_attr(&attributes,fname,tarmode,tartime);
> +-            }
> +-        }
> +-
> +-      /*
> +-       * Abandon if errors are found
> +-       */
> +-      if (action == TGZ_INVALID)
> +-        {
> +-          error("broken archive");
> +-          break;
> +-        }
> +-    }
> +-
> +-  /*
> +-   * Restore file modes and time stamps
> +-   */
> +-  restore_attr(&attributes);
> +-
> +-  if (gzclose(in) != Z_OK)
> +-    error("failed gzclose");
> +-
> +-  return 0;
> +-}
> +-
> +-
> +-/*
> ============================================================ */
> +-
> +-void help(int exitval)
> +-{
> +-  printf("untgz version 0.2.1\n"
> +-         "  using zlib version %s\n\n",
> +-         zlibVersion());
> +-  printf("Usage: untgz file.tgz            extract all files\n"
> +-         "       untgz file.tgz fname ...  extract selected files\n"
> +-         "       untgz -l file.tgz         list archive contents\n"
> +-         "       untgz -h                  display this help\n");
> +-  exit(exitval);
> +-}
> +-
> +-
> +-/*
> ============================================================ */
> +-
> +-#if defined(WIN32) && defined(__GNUC__)
> +-int _CRT_glob = 0;      /* disable argument globbing in MinGW */
> +-#endif
> +-
> +-int main(int argc,char **argv)
> +-{
> +-    int         action = TGZ_EXTRACT;
> +-    int         arg = 1;
> +-    char        *TGZfile;
> +-    gzFile      f;
> +-
> +-    prog = strrchr(argv[0],'\\');
> +-    if (prog == NULL)
> +-      {
> +-        prog = strrchr(argv[0],'/');
> +-        if (prog == NULL)
> +-          {
> +-            prog = strrchr(argv[0],':');
> +-            if (prog == NULL)
> +-              prog = argv[0];
> +-            else
> +-              prog++;
> +-          }
> +-        else
> +-          prog++;
> +-      }
> +-    else
> +-      prog++;
> +-
> +-    if (argc == 1)
> +-      help(0);
> +-
> +-    if (strcmp(argv[arg],"-l") == 0)
> +-      {
> +-        action = TGZ_LIST;
> +-        if (argc == ++arg)
> +-          help(0);
> +-      }
> +-    else if (strcmp(argv[arg],"-h") == 0)
> +-      {
> +-        help(0);
> +-      }
> +-
> +-    if ((TGZfile = TGZfname(argv[arg])) == NULL)
> +-      TGZnotfound(argv[arg]);
> +-
> +-    ++arg;
> +-    if ((action == TGZ_LIST) && (arg != argc))
> +-      help(1);
> +-
> +-/*
> +- *  Process the TGZ file
> +- */
> +-    switch(action)
> +-      {
> +-      case TGZ_LIST:
> +-      case TGZ_EXTRACT:
> +-        f = gzopen(TGZfile,"rb");
> +-        if (f == NULL)
> +-          {
> +-            fprintf(stderr,"%s: Couldn't gzopen %s\n",prog,TGZfile);
> +-            return 1;
> +-          }
> +-        exit(tar(f, action, arg, argc, argv));
> +-      break;
> +-
> +-      default:
> +-        error("Unknown option");
> +-        exit(1);
> +-      }
> +-
> +-    return 0;
> +-}
> +--
> +2.34.1
> +
> diff --git a/meta/recipes-core/zlib/zlib_1.3.1.bb b/meta/recipes-
> core/zlib/zlib_1.3.1.bb
> index 592b7f1422..cd6cdb6aa6 100644
> --- a/meta/recipes-core/zlib/zlib_1.3.1.bb
> +++ b/meta/recipes-core/zlib/zlib_1.3.1.bb
> @@ -9,6 +9,7 @@ LIC_FILES_CHKSUM =
> "file://zlib.h;beginline=6;endline=23;md5=5377232268e952e9ef6
>  # The source tarball needs to be .gz as only the .gz ends up in fossils/
>  SRC_URI = "https://zlib.net/${BP}.tar.gz \
>             file://0001-configure-Pass-LDFLAGS-to-link-tests.patch \
> +           file://CVE-2026-22184.patch \
>             file://run-ptest \
>             "
>  UPSTREAM_CHECK_URI = "http://zlib.net/"
> --
> 2.34.1
diff mbox series

Patch

diff --git a/meta/recipes-core/zlib/zlib/CVE-2026-22184.patch b/meta/recipes-core/zlib/zlib/CVE-2026-22184.patch
new file mode 100644
index 0000000000..130195d1ff
--- /dev/null
+++ b/meta/recipes-core/zlib/zlib/CVE-2026-22184.patch
@@ -0,0 +1,753 @@ 
+From 1a40058a92d525aa49a6eac698cfde500fc9b92f Mon Sep 17 00:00:00 2001
+From: Mark Adler <git@madler.net>
+Date: Sun, 11 Jan 2026 13:00:25 -0800
+Subject: [PATCH] Remove untgz from contrib.
+
+CVE: CVE-2026-22184
+
+Upstream-Status: Backport [https://github.com/madler/zlib/commit/1a40058a92d525aa49a6eac698cfde500fc9b92f]
+
+Signed-off-by: Mingli Yu <mingli.yu@windriver.com>
+---
+ contrib/README.contrib     |   3 -
+ contrib/untgz/Makefile     |  14 -
+ contrib/untgz/Makefile.msc |  17 -
+ contrib/untgz/untgz.c      | 667 -------------------------------------
+ 4 files changed, 701 deletions(-)
+ delete mode 100644 contrib/untgz/Makefile
+ delete mode 100644 contrib/untgz/Makefile.msc
+ delete mode 100644 contrib/untgz/untgz.c
+
+diff --git a/contrib/README.contrib b/contrib/README.contrib
+index 5e5f950..d9480ee 100644
+--- a/contrib/README.contrib
++++ b/contrib/README.contrib
+@@ -49,9 +49,6 @@ puff/       by Mark Adler <madler@alumni.caltech.edu>
+ testzlib/   by Gilles Vollant <info@winimage.com>
+         Example of the use of zlib
+ 
+-untgz/      by Pedro A. Aranda Gutierrez <paag@tid.es>
+-        A very simple tar.gz file extractor using zlib
+-
+ vstudio/    by Gilles Vollant <info@winimage.com>
+         Building a minizip-enhanced zlib with Microsoft Visual Studio
+         Includes vc11 from kreuzerkrieg and vc12 from davispuh
+diff --git a/contrib/untgz/Makefile b/contrib/untgz/Makefile
+deleted file mode 100644
+index b54266f..0000000
+--- a/contrib/untgz/Makefile
++++ /dev/null
+@@ -1,14 +0,0 @@
+-CC=cc
+-CFLAGS=-g
+-
+-untgz: untgz.o ../../libz.a
+-	$(CC) $(CFLAGS) -o untgz untgz.o -L../.. -lz
+-
+-untgz.o: untgz.c ../../zlib.h
+-	$(CC) $(CFLAGS) -c -I../.. untgz.c
+-
+-../../libz.a:
+-	cd ../..; ./configure; make
+-
+-clean:
+-	rm -f untgz untgz.o *~
+diff --git a/contrib/untgz/Makefile.msc b/contrib/untgz/Makefile.msc
+deleted file mode 100644
+index 77b8602..0000000
+--- a/contrib/untgz/Makefile.msc
++++ /dev/null
+@@ -1,17 +0,0 @@
+-CC=cl
+-CFLAGS=-MD
+-
+-untgz.exe: untgz.obj ..\..\zlib.lib
+-	$(CC) $(CFLAGS) untgz.obj ..\..\zlib.lib
+-
+-untgz.obj: untgz.c ..\..\zlib.h
+-	$(CC) $(CFLAGS) -c -I..\.. untgz.c
+-
+-..\..\zlib.lib:
+-	cd ..\..
+-	$(MAKE) -f win32\makefile.msc
+-	cd contrib\untgz
+-
+-clean:
+-	-del untgz.obj
+-	-del untgz.exe
+diff --git a/contrib/untgz/untgz.c b/contrib/untgz/untgz.c
+deleted file mode 100644
+index 7857921..0000000
+--- a/contrib/untgz/untgz.c
++++ /dev/null
+@@ -1,667 +0,0 @@
+-/*
+- * untgz.c -- Display contents and extract files from a gzip'd TAR file
+- *
+- * written by Pedro A. Aranda Gutierrez <paag@tid.es>
+- * adaptation to Unix by Jean-loup Gailly <jloup@gzip.org>
+- * various fixes by Cosmin Truta <cosmint@cs.ubbcluj.ro>
+- *
+- * This software is provided 'as-is', without any express or implied
+- * warranty.  In no event will the authors be held liable for any damages
+- * arising from the use of this software.
+- *
+- * Permission is granted to anyone to use this software for any purpose,
+- * including commercial applications, and to alter it and redistribute it
+- * freely, subject to the following restrictions:
+- *
+- * 1. The origin of this software must not be misrepresented; you must not
+- *    claim that you wrote the original software. If you use this software
+- *    in a product, an acknowledgment in the product documentation would be
+- *    appreciated but is not required.
+- * 2. Altered source versions must be plainly marked as such, and must not be
+- *    misrepresented as being the original software.
+- * 3. This notice may not be removed or altered from any source distribution.
+- */
+-
+-#include <stdio.h>
+-#include <stdlib.h>
+-#include <string.h>
+-#include <time.h>
+-#include <errno.h>
+-
+-#include "zlib.h"
+-
+-#ifdef _WIN32
+-#  include <direct.h>
+-#  include <io.h>
+-#  include <windows.h>
+-#  ifndef F_OK
+-#    define F_OK  0
+-#  endif
+-#  define mkdir(dirname,mode)   _mkdir(dirname)
+-#  ifdef _MSC_VER
+-#    define access(path,mode)   _access(path,mode)
+-#    define chmod(path,mode)    _chmod(path,mode)
+-#    define strdup(str)         _strdup(str)
+-#  endif
+-#else
+-#  include <sys/stat.h>
+-#  include <unistd.h>
+-#  include <utime.h>
+-#endif
+-
+-
+-/* values used in typeflag field */
+-
+-#define REGTYPE  '0'            /* regular file */
+-#define AREGTYPE '\0'           /* regular file */
+-#define LNKTYPE  '1'            /* link */
+-#define SYMTYPE  '2'            /* reserved */
+-#define CHRTYPE  '3'            /* character special */
+-#define BLKTYPE  '4'            /* block special */
+-#define DIRTYPE  '5'            /* directory */
+-#define FIFOTYPE '6'            /* FIFO special */
+-#define CONTTYPE '7'            /* reserved */
+-
+-/* GNU tar extensions */
+-
+-#define GNUTYPE_DUMPDIR  'D'    /* file names from dumped directory */
+-#define GNUTYPE_LONGLINK 'K'    /* long link name */
+-#define GNUTYPE_LONGNAME 'L'    /* long file name */
+-#define GNUTYPE_MULTIVOL 'M'    /* continuation of file from another volume */
+-#define GNUTYPE_NAMES    'N'    /* file name that does not fit into main hdr */
+-#define GNUTYPE_SPARSE   'S'    /* sparse file */
+-#define GNUTYPE_VOLHDR   'V'    /* tape/volume header */
+-
+-
+-/* tar header */
+-
+-#define BLOCKSIZE     512
+-#define SHORTNAMESIZE 100
+-
+-struct tar_header
+-{                               /* byte offset */
+-  char name[100];               /*   0 */
+-  char mode[8];                 /* 100 */
+-  char uid[8];                  /* 108 */
+-  char gid[8];                  /* 116 */
+-  char size[12];                /* 124 */
+-  char mtime[12];               /* 136 */
+-  char chksum[8];               /* 148 */
+-  char typeflag;                /* 156 */
+-  char linkname[100];           /* 157 */
+-  char magic[6];                /* 257 */
+-  char version[2];              /* 263 */
+-  char uname[32];               /* 265 */
+-  char gname[32];               /* 297 */
+-  char devmajor[8];             /* 329 */
+-  char devminor[8];             /* 337 */
+-  char prefix[155];             /* 345 */
+-                                /* 500 */
+-};
+-
+-union tar_buffer
+-{
+-  char               buffer[BLOCKSIZE];
+-  struct tar_header  header;
+-};
+-
+-struct attr_item
+-{
+-  struct attr_item  *next;
+-  char              *fname;
+-  int                mode;
+-  time_t             time;
+-};
+-
+-enum { TGZ_EXTRACT, TGZ_LIST, TGZ_INVALID };
+-
+-char *prog;
+-
+-void error(const char *msg)
+-{
+-  fprintf(stderr, "%s: %s\n", prog, msg);
+-  exit(1);
+-}
+-
+-const char *TGZsuffix[] = { "\0", ".tar", ".tar.gz", ".taz", ".tgz", NULL };
+-
+-/* return the file name of the TGZ archive */
+-/* or NULL if it does not exist */
+-
+-char *TGZfname (const char *arcname)
+-{
+-  static char buffer[1024];
+-  int origlen,i;
+-
+-  strcpy(buffer,arcname);
+-  origlen = strlen(buffer);
+-
+-  for (i=0; TGZsuffix[i]; i++)
+-    {
+-       strcpy(buffer+origlen,TGZsuffix[i]);
+-       if (access(buffer,F_OK) == 0)
+-         return buffer;
+-    }
+-  return NULL;
+-}
+-
+-
+-/* error message for the filename */
+-
+-void TGZnotfound (const char *arcname)
+-{
+-  int i;
+-
+-  fprintf(stderr,"%s: Couldn't find ",prog);
+-  for (i=0;TGZsuffix[i];i++)
+-    fprintf(stderr,(TGZsuffix[i+1]) ? "%s%s, " : "or %s%s\n",
+-            arcname,
+-            TGZsuffix[i]);
+-  exit(1);
+-}
+-
+-
+-/* convert octal digits to int */
+-/* on error return -1 */
+-
+-int getoct (char *p,int width)
+-{
+-  int result = 0;
+-  char c;
+-
+-  while (width--)
+-    {
+-      c = *p++;
+-      if (c == 0)
+-        break;
+-      if (c == ' ')
+-        continue;
+-      if (c < '0' || c > '7')
+-        return -1;
+-      result = result * 8 + (c - '0');
+-    }
+-  return result;
+-}
+-
+-
+-/* convert time_t to string */
+-/* use the "YYYY/MM/DD hh:mm:ss" format */
+-
+-char *strtime (time_t *t)
+-{
+-  struct tm   *local;
+-  static char result[32];
+-
+-  local = localtime(t);
+-  sprintf(result,"%4d/%02d/%02d %02d:%02d:%02d",
+-          local->tm_year+1900, local->tm_mon+1, local->tm_mday,
+-          local->tm_hour, local->tm_min, local->tm_sec);
+-  return result;
+-}
+-
+-
+-/* set file time */
+-
+-int setfiletime (char *fname,time_t ftime)
+-{
+-#ifdef _WIN32
+-  static int isWinNT = -1;
+-  SYSTEMTIME st;
+-  FILETIME locft, modft;
+-  struct tm *loctm;
+-  HANDLE hFile;
+-  int result;
+-
+-  loctm = localtime(&ftime);
+-  if (loctm == NULL)
+-    return -1;
+-
+-  st.wYear         = (WORD)loctm->tm_year + 1900;
+-  st.wMonth        = (WORD)loctm->tm_mon + 1;
+-  st.wDayOfWeek    = (WORD)loctm->tm_wday;
+-  st.wDay          = (WORD)loctm->tm_mday;
+-  st.wHour         = (WORD)loctm->tm_hour;
+-  st.wMinute       = (WORD)loctm->tm_min;
+-  st.wSecond       = (WORD)loctm->tm_sec;
+-  st.wMilliseconds = 0;
+-  if (!SystemTimeToFileTime(&st, &locft) ||
+-      !LocalFileTimeToFileTime(&locft, &modft))
+-    return -1;
+-
+-  if (isWinNT < 0)
+-    isWinNT = (GetVersion() < 0x80000000) ? 1 : 0;
+-  hFile = CreateFile(fname, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
+-                     (isWinNT ? FILE_FLAG_BACKUP_SEMANTICS : 0),
+-                     NULL);
+-  if (hFile == INVALID_HANDLE_VALUE)
+-    return -1;
+-  result = SetFileTime(hFile, NULL, NULL, &modft) ? 0 : -1;
+-  CloseHandle(hFile);
+-  return result;
+-#else
+-  struct utimbuf settime;
+-
+-  settime.actime = settime.modtime = ftime;
+-  return utime(fname,&settime);
+-#endif
+-}
+-
+-
+-/* push file attributes */
+-
+-void push_attr(struct attr_item **list,char *fname,int mode,time_t time)
+-{
+-  struct attr_item *item;
+-
+-  item = (struct attr_item *)malloc(sizeof(struct attr_item));
+-  if (item == NULL)
+-    error("Out of memory");
+-  item->fname = strdup(fname);
+-  item->mode  = mode;
+-  item->time  = time;
+-  item->next  = *list;
+-  *list       = item;
+-}
+-
+-
+-/* restore file attributes */
+-
+-void restore_attr(struct attr_item **list)
+-{
+-  struct attr_item *item, *prev;
+-
+-  for (item = *list; item != NULL; )
+-    {
+-      setfiletime(item->fname,item->time);
+-      chmod(item->fname,item->mode);
+-      prev = item;
+-      item = item->next;
+-      free(prev);
+-    }
+-  *list = NULL;
+-}
+-
+-
+-/* match regular expression */
+-
+-#define ISSPECIAL(c) (((c) == '*') || ((c) == '/'))
+-
+-int ExprMatch (char *string,char *expr)
+-{
+-  while (1)
+-    {
+-      if (ISSPECIAL(*expr))
+-        {
+-          if (*expr == '/')
+-            {
+-              if (*string != '\\' && *string != '/')
+-                return 0;
+-              string ++; expr++;
+-            }
+-          else if (*expr == '*')
+-            {
+-              if (*expr ++ == 0)
+-                return 1;
+-              while (*++string != *expr)
+-                if (*string == 0)
+-                  return 0;
+-            }
+-        }
+-      else
+-        {
+-          if (*string != *expr)
+-            return 0;
+-          if (*expr++ == 0)
+-            return 1;
+-          string++;
+-        }
+-    }
+-}
+-
+-
+-/* recursive mkdir */
+-/* abort on ENOENT; ignore other errors like "directory already exists" */
+-/* return 1 if OK */
+-/*        0 on error */
+-
+-int makedir (char *newdir)
+-{
+-  char *buffer = strdup(newdir);
+-  char *p;
+-  int  len = strlen(buffer);
+-
+-  if (len <= 0) {
+-    free(buffer);
+-    return 0;
+-  }
+-  if (buffer[len-1] == '/') {
+-    buffer[len-1] = '\0';
+-  }
+-  if (mkdir(buffer, 0755) == 0)
+-    {
+-      free(buffer);
+-      return 1;
+-    }
+-
+-  p = buffer+1;
+-  while (1)
+-    {
+-      char hold;
+-
+-      while(*p && *p != '\\' && *p != '/')
+-        p++;
+-      hold = *p;
+-      *p = 0;
+-      if ((mkdir(buffer, 0755) == -1) && (errno == ENOENT))
+-        {
+-          fprintf(stderr,"%s: Couldn't create directory %s\n",prog,buffer);
+-          free(buffer);
+-          return 0;
+-        }
+-      if (hold == 0)
+-        break;
+-      *p++ = hold;
+-    }
+-  free(buffer);
+-  return 1;
+-}
+-
+-
+-int matchname (int arg,int argc,char **argv,char *fname)
+-{
+-  if (arg == argc)      /* no arguments given (untgz tgzarchive) */
+-    return 1;
+-
+-  while (arg < argc)
+-    if (ExprMatch(fname,argv[arg++]))
+-      return 1;
+-
+-  return 0; /* ignore this for the moment being */
+-}
+-
+-
+-/* tar file list or extract */
+-
+-int tar (gzFile in,int action,int arg,int argc,char **argv)
+-{
+-  union  tar_buffer buffer;
+-  int    len;
+-  int    err;
+-  int    getheader = 1;
+-  int    remaining = 0;
+-  FILE   *outfile = NULL;
+-  char   fname[BLOCKSIZE];
+-  int    tarmode;
+-  time_t tartime;
+-  struct attr_item *attributes = NULL;
+-
+-  if (action == TGZ_LIST)
+-    printf("    date      time     size                       file\n"
+-           " ---------- -------- --------- -------------------------------------\n");
+-  while (1)
+-    {
+-      len = gzread(in, &buffer, BLOCKSIZE);
+-      if (len < 0)
+-        error(gzerror(in, &err));
+-      /*
+-       * Always expect complete blocks to process
+-       * the tar information.
+-       */
+-      if (len != BLOCKSIZE)
+-        {
+-          action = TGZ_INVALID; /* force error exit */
+-          remaining = 0;        /* force I/O cleanup */
+-        }
+-
+-      /*
+-       * If we have to get a tar header
+-       */
+-      if (getheader >= 1)
+-        {
+-          /*
+-           * if we met the end of the tar
+-           * or the end-of-tar block,
+-           * we are done
+-           */
+-          if (len == 0 || buffer.header.name[0] == 0)
+-            break;
+-
+-          tarmode = getoct(buffer.header.mode,8);
+-          tartime = (time_t)getoct(buffer.header.mtime,12);
+-          if (tarmode == -1 || tartime == (time_t)-1)
+-            {
+-              buffer.header.name[0] = 0;
+-              action = TGZ_INVALID;
+-            }
+-
+-          if (getheader == 1)
+-            {
+-              strncpy(fname,buffer.header.name,SHORTNAMESIZE);
+-              if (fname[SHORTNAMESIZE-1] != 0)
+-                  fname[SHORTNAMESIZE] = 0;
+-            }
+-          else
+-            {
+-              /*
+-               * The file name is longer than SHORTNAMESIZE
+-               */
+-              if (strncmp(fname,buffer.header.name,SHORTNAMESIZE-1) != 0)
+-                  error("bad long name");
+-              getheader = 1;
+-            }
+-
+-          /*
+-           * Act according to the type flag
+-           */
+-          switch (buffer.header.typeflag)
+-            {
+-            case DIRTYPE:
+-              if (action == TGZ_LIST)
+-                printf(" %s     <dir> %s\n",strtime(&tartime),fname);
+-              if (action == TGZ_EXTRACT)
+-                {
+-                  makedir(fname);
+-                  push_attr(&attributes,fname,tarmode,tartime);
+-                }
+-              break;
+-            case REGTYPE:
+-            case AREGTYPE:
+-              remaining = getoct(buffer.header.size,12);
+-              if (remaining == -1)
+-                {
+-                  action = TGZ_INVALID;
+-                  break;
+-                }
+-              if (action == TGZ_LIST)
+-                printf(" %s %9d %s\n",strtime(&tartime),remaining,fname);
+-              else if (action == TGZ_EXTRACT)
+-                {
+-                  if (matchname(arg,argc,argv,fname))
+-                    {
+-                      outfile = fopen(fname,"wb");
+-                      if (outfile == NULL) {
+-                        /* try creating directory */
+-                        char *p = strrchr(fname, '/');
+-                        if (p != NULL) {
+-                          *p = '\0';
+-                          makedir(fname);
+-                          *p = '/';
+-                          outfile = fopen(fname,"wb");
+-                        }
+-                      }
+-                      if (outfile != NULL)
+-                        printf("Extracting %s\n",fname);
+-                      else
+-                        fprintf(stderr, "%s: Couldn't create %s",prog,fname);
+-                    }
+-                  else
+-                    outfile = NULL;
+-                }
+-              getheader = 0;
+-              break;
+-            case GNUTYPE_LONGLINK:
+-            case GNUTYPE_LONGNAME:
+-              remaining = getoct(buffer.header.size,12);
+-              if (remaining < 0 || remaining >= BLOCKSIZE)
+-                {
+-                  action = TGZ_INVALID;
+-                  break;
+-                }
+-              len = gzread(in, fname, BLOCKSIZE);
+-              if (len < 0)
+-                error(gzerror(in, &err));
+-              if (fname[BLOCKSIZE-1] != 0 || (int)strlen(fname) > remaining)
+-                {
+-                  action = TGZ_INVALID;
+-                  break;
+-                }
+-              getheader = 2;
+-              break;
+-            default:
+-              if (action == TGZ_LIST)
+-                printf(" %s     <---> %s\n",strtime(&tartime),fname);
+-              break;
+-            }
+-        }
+-      else
+-        {
+-          unsigned int bytes = (remaining > BLOCKSIZE) ? BLOCKSIZE : remaining;
+-
+-          if (outfile != NULL)
+-            {
+-              if (fwrite(&buffer,sizeof(char),bytes,outfile) != bytes)
+-                {
+-                  fprintf(stderr,
+-                    "%s: Error writing %s -- skipping\n",prog,fname);
+-                  fclose(outfile);
+-                  outfile = NULL;
+-                  remove(fname);
+-                }
+-            }
+-          remaining -= bytes;
+-        }
+-
+-      if (remaining == 0)
+-        {
+-          getheader = 1;
+-          if (outfile != NULL)
+-            {
+-              fclose(outfile);
+-              outfile = NULL;
+-              if (action != TGZ_INVALID)
+-                push_attr(&attributes,fname,tarmode,tartime);
+-            }
+-        }
+-
+-      /*
+-       * Abandon if errors are found
+-       */
+-      if (action == TGZ_INVALID)
+-        {
+-          error("broken archive");
+-          break;
+-        }
+-    }
+-
+-  /*
+-   * Restore file modes and time stamps
+-   */
+-  restore_attr(&attributes);
+-
+-  if (gzclose(in) != Z_OK)
+-    error("failed gzclose");
+-
+-  return 0;
+-}
+-
+-
+-/* ============================================================ */
+-
+-void help(int exitval)
+-{
+-  printf("untgz version 0.2.1\n"
+-         "  using zlib version %s\n\n",
+-         zlibVersion());
+-  printf("Usage: untgz file.tgz            extract all files\n"
+-         "       untgz file.tgz fname ...  extract selected files\n"
+-         "       untgz -l file.tgz         list archive contents\n"
+-         "       untgz -h                  display this help\n");
+-  exit(exitval);
+-}
+-
+-
+-/* ============================================================ */
+-
+-#if defined(WIN32) && defined(__GNUC__)
+-int _CRT_glob = 0;      /* disable argument globbing in MinGW */
+-#endif
+-
+-int main(int argc,char **argv)
+-{
+-    int         action = TGZ_EXTRACT;
+-    int         arg = 1;
+-    char        *TGZfile;
+-    gzFile      f;
+-
+-    prog = strrchr(argv[0],'\\');
+-    if (prog == NULL)
+-      {
+-        prog = strrchr(argv[0],'/');
+-        if (prog == NULL)
+-          {
+-            prog = strrchr(argv[0],':');
+-            if (prog == NULL)
+-              prog = argv[0];
+-            else
+-              prog++;
+-          }
+-        else
+-          prog++;
+-      }
+-    else
+-      prog++;
+-
+-    if (argc == 1)
+-      help(0);
+-
+-    if (strcmp(argv[arg],"-l") == 0)
+-      {
+-        action = TGZ_LIST;
+-        if (argc == ++arg)
+-          help(0);
+-      }
+-    else if (strcmp(argv[arg],"-h") == 0)
+-      {
+-        help(0);
+-      }
+-
+-    if ((TGZfile = TGZfname(argv[arg])) == NULL)
+-      TGZnotfound(argv[arg]);
+-
+-    ++arg;
+-    if ((action == TGZ_LIST) && (arg != argc))
+-      help(1);
+-
+-/*
+- *  Process the TGZ file
+- */
+-    switch(action)
+-      {
+-      case TGZ_LIST:
+-      case TGZ_EXTRACT:
+-        f = gzopen(TGZfile,"rb");
+-        if (f == NULL)
+-          {
+-            fprintf(stderr,"%s: Couldn't gzopen %s\n",prog,TGZfile);
+-            return 1;
+-          }
+-        exit(tar(f, action, arg, argc, argv));
+-      break;
+-
+-      default:
+-        error("Unknown option");
+-        exit(1);
+-      }
+-
+-    return 0;
+-}
+-- 
+2.34.1
+
diff --git a/meta/recipes-core/zlib/zlib_1.3.1.bb b/meta/recipes-core/zlib/zlib_1.3.1.bb
index 592b7f1422..cd6cdb6aa6 100644
--- a/meta/recipes-core/zlib/zlib_1.3.1.bb
+++ b/meta/recipes-core/zlib/zlib_1.3.1.bb
@@ -9,6 +9,7 @@  LIC_FILES_CHKSUM = "file://zlib.h;beginline=6;endline=23;md5=5377232268e952e9ef6
 # The source tarball needs to be .gz as only the .gz ends up in fossils/
 SRC_URI = "https://zlib.net/${BP}.tar.gz \
            file://0001-configure-Pass-LDFLAGS-to-link-tests.patch \
+           file://CVE-2026-22184.patch \
            file://run-ptest \
            "
 UPSTREAM_CHECK_URI = "http://zlib.net/"