[packages/tnef] updated to 1.4.18

arekm arekm at pld-linux.org
Sun Oct 18 20:57:13 CEST 2026


commit 521e52ea3a2fec26d9c283df2dd22deb34b9a65e
Author: Arkadiusz Miśkiewicz <arekm at maven.pl>
Date:   Sun Oct 18 20:56:01 2026 +0200

    updated to 1.4.18
    
    Fixes CVE-2026-103678, CVE-2026-103679, CVE-2026-103680.

 tnef-CVE-2026-103678.patch     | 48 +++++++++++++++++++++++++++++
 tnef-CVE-2026-103679.patch     | 43 ++++++++++++++++++++++++++
 tnef-CVE-2026-103680.patch     | 69 ++++++++++++++++++++++++++++++++++++++++++
 tnef-attr_read-prototype.patch | 16 ++++++++++
 tnef.spec                      | 30 +++++++++++++++---
 5 files changed, 201 insertions(+), 5 deletions(-)
---
diff --git a/tnef.spec b/tnef.spec
index 1bb79f8..5216bc0 100644
--- a/tnef.spec
+++ b/tnef.spec
@@ -1,17 +1,28 @@
+#
+# Conditional build:
+%bcond_without	tests		# build with tests
+
 Summary:	Decodes MS-TNEF attachments
 Summary(pl.UTF-8):	Dekoder załączników w formacie MS-TNEF
 Summary(ru.UTF-8):	Программа для распаковки аттачментов MIME типа "application/ms-tnef"
 Summary(uk.UTF-8):	Програма для розпаковки атачментів MIME типу "application/ms-tnef"
 Name:		tnef
-Version:	1.4.12
+Version:	1.4.18
 Release:	1
 License:	GPL v2+
 Group:		Applications/Mail
-Source0:	http://downloads.sourceforge.net/tnef/%{name}-%{version}.tar.gz
-# Source0-md5:	92b27d6ff4374fea28b04e38032c7710
-URL:		http://sourceforge.net/projects/tnef/
+Source0:	https://github.com/verdammelt/%{name}/archive/refs/tags/%{version}/%{name}-%{version}.tar.gz
+# Source0-md5:	c18c0166aaf5d19355394515978480e6
+Patch0:		%{name}-attr_read-prototype.patch
+Patch1:		%{name}-CVE-2026-103678.patch
+Patch2:		%{name}-CVE-2026-103679.patch
+Patch3:		%{name}-CVE-2026-103680.patch
+URL:		https://github.com/verdammelt/%{name}
 BuildRequires:	autoconf >= 2.59
 BuildRequires:	automake
+%if %{with tests}
+BuildRequires:	diffutils
+%endif
 BuildRoot:	%{tmpdir}/%{name}-%{version}-root-%(id -u -n)
 
 %description
@@ -48,6 +59,10 @@ TNEF - це програма для розпаковки атачментів MI
 
 %prep
 %setup -q
+%patch -P0 -p1
+%patch -P1 -p1
+%patch -P2 -p1
+%patch -P3 -p1
 
 %build
 %{__aclocal}
@@ -57,6 +72,11 @@ TNEF - це програма для розпаковки атачментів MI
 %configure
 %{__make}
 
+%if %{with tests}
+# tests share one working directory, so they cannot run in parallel
+%{__make} -j1 check
+%endif
+
 %install
 rm -rf $RPM_BUILD_ROOT
 
@@ -68,6 +88,6 @@ rm -rf $RPM_BUILD_ROOT
 
 %files
 %defattr(644,root,root,755)
-%doc AUTHORS BUGS ChangeLog NEWS README.md THANKS doc/{FAQ,file-format.tex}
+%doc AUTHORS BUGS ChangeLog NEWS README.md THANKS doc/{FAQ,file-format.txt}
 %attr(755,root,root) %{_bindir}/tnef
 %{_mandir}/man1/tnef.1*
diff --git a/tnef-CVE-2026-103678.patch b/tnef-CVE-2026-103678.patch
new file mode 100644
index 0000000..18f80f6
--- /dev/null
+++ b/tnef-CVE-2026-103678.patch
@@ -0,0 +1,48 @@
+get_rtf_data_from_buf() trusts the uncompressed size in the RTF value
+header and memmove()s that many bytes out of a buffer that only holds the
+declared compressed size.  An uncompressed ("MELA") RTF value with an
+oversized uncompressed size therefore reads past the end of the heap
+buffer; with --save-body the over-read bytes end up in the extracted file.
+
+CVE-2026-103678
+Reported via https://bugzilla.redhat.com/show_bug.cgi?id=2544476
+Upstream proposal: https://github.com/verdammelt/tnef/pull/54
+From that pull request only the assert placement is used: it does not hold
+for uncompressed values, so it now sits in the compressed branch.  The
+pull request itself just turns the over-read into an abort under assert(),
+which disappears in NDEBUG builds, so an explicit size check is done here.
+--- a/src/rtf.c
++++ b/src/rtf.c
+@@ -316,18 +316,29 @@
+     magic = GETINT32(data + idx); idx += 4;
+     checksum = GETINT32 (data + idx); idx += 4;
+ 
+-    /* sanity check */
+-    assert (compr_size + 4 == len);
+-
+     (*out_len) = uncompr_size;
+ 
+     if (magic == rtf_uncompressed_magic) /* uncompressed rtf stream */
+     {
++        /* the uncompressed stream is copied straight out of the value
++           buffer, so its declared size cannot exceed what is left of
++           that buffer */
++        if (uncompr_size > len - 4)
++        {
++            (*out_data) = CHECKED_XCALLOC(unsigned char, 4);
++            (*out_len) = 0;
++            fprintf( stderr, "RTF size larger than buffer, input file may be corrupted\n" );
++            return;
++        }
++
+         (*out_data) = CHECKED_XCALLOC(unsigned char, (*out_len));
+         memmove ((*out_data), data+4, uncompr_size);
+     }
+     else if (magic == rtf_compressed_magic) /* compressed rtf stream */
+     {
++        /* sanity check */
++        assert (compr_size + 4 == len);
++
+         if ( checksum == generate_crc( data+idx, len-idx ) )
+         {
+             (*out_data) = decompress_rtf_data (data+idx, len-idx, uncompr_size);
diff --git a/tnef-CVE-2026-103679.patch b/tnef-CVE-2026-103679.patch
new file mode 100644
index 0000000..a5f68d6
--- /dev/null
+++ b/tnef-CVE-2026-103679.patch
@@ -0,0 +1,43 @@
+get_body_files() allocates the output file name and the MIME type once and
+points every generated file at the same buffers.  When a TNEF stream
+carries more than one body value, each File is freed separately, so the
+second and later files free memory that was already freed: use after free
+followed by double free.
+
+CVE-2026-103679
+Reported via https://bugzilla.redhat.com/show_bug.cgi?id=2544477
+No upstream fix at the time of writing: still present in upstream git
+master and unpatched in Debian and Fedora, and no pull request either.
+This fix is PLD's.
+--- a/src/tnef.c
++++ b/src/tnef.c
+@@ -126,9 +126,6 @@
+         strcpy (tmp, filename);
+         strcat (tmp, ext);
+ 
+-        char *mime = CHECKED_XCALLOC(char, strlen(type) + 1);
+-        strcpy (mime, type);
+-
+         /* first get a count */
+         while (data[count++]);
+ 
+@@ -136,13 +133,17 @@
+         for (i = 0; data[i]; i++)
+         {
+             files[i] = (File*)XCALLOC(File, 1);
+-            files[i]->name = tmp;
+-            files[i]->mime_type = mime;
++            /* every file owns its own name and mime type, so that each
++               of them can be freed independently */
++            files[i]->name = xstrdup (tmp);
++            files[i]->mime_type = xstrdup (type);
+             files[i]->len = data[i]->len;
+             files[i]->data
+                 = CHECKED_XMALLOC(unsigned char, data[i]->len);
+             memmove (files[i]->data, data[i]->data, data[i]->len);
+         }
++
++        XFREE (tmp);
+     }
+     return files;
+ }
diff --git a/tnef-CVE-2026-103680.patch b/tnef-CVE-2026-103680.patch
new file mode 100644
index 0000000..c070e79
--- /dev/null
+++ b/tnef-CVE-2026-103680.patch
@@ -0,0 +1,69 @@
+find_free_number() sizes its buffer for a five digit numeric suffix but
+formats the counter with sprintf() without any bound.  With
+--number-backups and without --overwrite, a stream with enough colliding
+attachment names pushes the counter past 99999 and sprintf() writes past
+the end of the heap buffer.
+
+CVE-2026-103680
+Reported via https://bugzilla.redhat.com/show_bug.cgi?id=2544478
+Taken from upstream pull request https://github.com/verdammelt/tnef/pull/53
+by suve <veg at svgames.pl>: the buffer is sized for a full width unsigned
+counter, the counter becomes unsigned and gives up (returning NULL) when
+exhausted; the caller reports the failure instead of writing the file.
+--- a/src/path.c
++++ b/src/path.c
+@@ -25,6 +25,7 @@
+ 
+ #include "common.h"
+ #include <ctype.h>
++#include <limits.h>
+ 
+ #if HAVE_SYS_STAT_H
+ #  include <sys/stat.h>
+@@ -102,16 +103,19 @@
+ {
+     size_t len = (strlen(fname)
+                   + 1	/* '.' */
+-                  + 5	/* big enough for our purposes (i hope) */
++                  + 20	/* if unsigned int is 64 bits, 2**64-1 is 20 decimal digits */
+                   + 1);	/* NULL */
+     char *tmp = CHECKED_XMALLOC (char, len);
+-    int counter = 1;
++    unsigned int counter = 0;
+     do
+     {
+-        sprintf (tmp, "%s.%d", fname, counter++);
++        sprintf (tmp, "%s.%u", fname, ++counter);
++        if (!file_exists(tmp)) return tmp;
+     }
+-    while (file_exists(tmp));
+-    return tmp;
++    while (counter < UINT_MAX);
++
++    XFREE(tmp);
++    return NULL;
+ }
+ 
+ /* windows pathname manipulation routines */
+--- a/src/file.c
++++ b/src/file.c
+@@ -112,9 +112,16 @@
+                 else
+                 {
+                     char *tmp = find_free_number (path);
+-                    debug_print ("Renaming %s to %s\n", path, tmp);
+-                    XFREE (path);
+-                    path = tmp;
++                    if (tmp != NULL) {
++                        debug_print ("Renaming %s to %s\n", path, tmp);
++                        XFREE (path);
++                        path = tmp;
++                    } else {
++                        fprintf (stderr,
++                                 "tnef: %s: Could not create file: File exists, all alternative names tried\n",
++                                 path);
++                        return;
++                    }
+                 }
+             }
+         }
diff --git a/tnef-attr_read-prototype.patch b/tnef-attr_read-prototype.patch
new file mode 100644
index 0000000..0d2126f
--- /dev/null
+++ b/tnef-attr_read-prototype.patch
@@ -0,0 +1,16 @@
+attr_read() is called with a FILE* argument, but declared as taking none.
+GCC 14 rejects the mismatch in attr.c as an error.
+
+Upstream commit 86bfa75cfacbe71c8d5282fa0065981b4544c5ad
+https://github.com/verdammelt/tnef/commit/86bfa75cfacbe71c8d5282fa0065981b4544c5ad
+
+--- a/src/attr.h
++++ b/src/attr.h
+@@ -69,6 +69,6 @@
+ extern void attr_dump (Attr* attr);
+ extern void attr_free (Attr* attr);
+ extern void copy_date_from_attr (Attr* attr, struct date* dt);
+-extern Attr* attr_read ();
++extern Attr* attr_read (FILE* in);
+ 
+ #endif /* ATTR_H */
================================================================

---- gitweb:

http://git.pld-linux.org/gitweb.cgi/packages/tnef.git/commitdiff/521e52ea3a2fec26d9c283df2dd22deb34b9a65e



More information about the pld-cvs-commit mailing list