Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package podofo for openSUSE:Factory checked 
in at 2024-09-25 21:51:41
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/podofo (Old)
 and      /work/SRC/openSUSE:Factory/.podofo.new.29891 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "podofo"

Wed Sep 25 21:51:41 2024 rev:39 rq:1203389 version:0.10.4

Changes:
--------
--- /work/SRC/openSUSE:Factory/podofo/podofo.changes    2024-08-20 
16:13:15.081807566 +0200
+++ /work/SRC/openSUSE:Factory/.podofo.new.29891/podofo.changes 2024-09-25 
21:51:46.696504218 +0200
@@ -1,0 +2,21 @@
+Sun Sep  8 07:50:21 UTC 2024 - Cliff Zhao <qz...@suse.com>
+
+- Add podofo-CVE-2019-20093.patch:
+  Backport from upstream proposed fix, Fix denial of service
+  (NULL pointer dereference) in PoDoFo::PdfVariant::DelayedLoad
+  function in PdfVariant.h.
+  https://sourceforge.net/p/podofo/tickets/75/
+  (CVE-2019-20093, bsc#1159921)
+
+-------------------------------------------------------------------
+Sat Sep  7 17:53:18 UTC 2024 - Cliff Zhao <qz...@suse.com>
+
+- update to 0.10.4:
+  * StandardStreamDevice: Fixed seek() in case of iostream/fstream
+  * PdfWriter: Fixed computing the doc identifier with a wrong buffer
+  * PdfPainter: Fix SetCurrentMatrix() to really update CTM
+  * Fixed compilation in mingw < 12
+  * PdfCIDToGIDMap: Fixed map reading
+  * PdfPainter: Fixed offset on multiline text if text is not left aligned
+
+-------------------------------------------------------------------
@@ -28,0 +50,3 @@
+    (bsc#1213720)
+  - PdfEncrypt: Validate more encrypt dictionary parameters
+    (bsc#1213720)

Old:
----
  podofo-0.10.3.tar.gz

New:
----
  podofo-0.10.4.tar.gz
  podofo-CVE-2019-20093.patch

BETA DEBUG BEGIN:
  New:
- Add podofo-CVE-2019-20093.patch:
  Backport from upstream proposed fix, Fix denial of service
BETA DEBUG END:

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ podofo.spec ++++++
--- /var/tmp/diff_new_pack.nJpZP1/_old  2024-09-25 21:51:47.184524546 +0200
+++ /var/tmp/diff_new_pack.nJpZP1/_new  2024-09-25 21:51:47.184524546 +0200
@@ -19,7 +19,7 @@
 %define libver 2
 %bcond_with tools
 Name:           podofo
-Version:        0.10.3
+Version:        0.10.4
 Release:        0
 Summary:        Tools to work with PDF files
 License:        GPL-2.0-or-later
@@ -28,6 +28,7 @@
 Source0:        
https://github.com/podofo/podofo/archive/%{version}/%{name}-%{version}.tar.gz
 # PATCH-FIX-OPENSUSE: manuals does not build
 Patch0:         podofo-tools_man.patch
+Patch1:         podofo-CVE-2019-20093.patch
 BuildRequires:  cmake >= 2.6
 BuildRequires:  doxygen
 BuildRequires:  fdupes

++++++ podofo-0.10.3.tar.gz -> podofo-0.10.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podofo-0.10.3/.github/workflows/build-mac.yml 
new/podofo-0.10.4/.github/workflows/build-mac.yml
--- old/podofo-0.10.3/.github/workflows/build-mac.yml   2023-11-28 
10:23:37.000000000 +0100
+++ new/podofo-0.10.4/.github/workflows/build-mac.yml   2024-09-12 
21:14:33.000000000 +0200
@@ -10,12 +10,15 @@
       ctestArgs:
         description: 'CTest arguments'
 
+# NOTE: Don't update other tools with broken linkage with
+# HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK. See 
https://docs.brew.sh/Manpage#install-options-formulacask-
 env:
   BUILD_TYPE: Release
+  HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1
 
 jobs:
   build:
-    runs-on: macos-11
+    runs-on: macos-12
 
     steps:
     - uses: actions/checkout@v2
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podofo-0.10.3/CHANGELOG.md 
new/podofo-0.10.4/CHANGELOG.md
--- old/podofo-0.10.3/CHANGELOG.md      2023-11-28 10:23:37.000000000 +0100
+++ new/podofo-0.10.4/CHANGELOG.md      2024-09-12 21:14:33.000000000 +0200
@@ -1,3 +1,6 @@
+# Version 0.10.4
+- Fixed seek() in case of iostream/fstream used with StandardStreamDevice
+
 # Version 0.10.3
 - Fixed big performance regression introduced in 0.10, see #108
 - Fixed data loss with encrypted documents, see #99
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podofo-0.10.3/CMakeLists.txt 
new/podofo-0.10.4/CMakeLists.txt
--- old/podofo-0.10.3/CMakeLists.txt    2023-11-28 10:23:37.000000000 +0100
+++ new/podofo-0.10.4/CMakeLists.txt    2024-09-12 21:14:33.000000000 +0200
@@ -20,7 +20,7 @@
 
 set(PODOFO_VERSION_MAJOR "0" CACHE STRING "Major part of podofo version 
number")
 set(PODOFO_VERSION_MINOR "10" CACHE STRING "Minor part of podofo version 
number")
-set(PODOFO_VERSION_PATCH "3" CACHE STRING "Patchlevel part of podofo version 
number")
+set(PODOFO_VERSION_PATCH "4" CACHE STRING "Patchlevel part of podofo version 
number")
 set(PODOFO_VERSION 
"${PODOFO_VERSION_MAJOR}.${PODOFO_VERSION_MINOR}.${PODOFO_VERSION_PATCH}")
 set(PODOFO_SOVERSION "2")
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podofo-0.10.3/src/podofo/auxiliary/StreamDevice.cpp 
new/podofo-0.10.4/src/podofo/auxiliary/StreamDevice.cpp
--- old/podofo-0.10.3/src/podofo/auxiliary/StreamDevice.cpp     2023-11-28 
10:23:37.000000000 +0100
+++ new/podofo-0.10.4/src/podofo/auxiliary/StreamDevice.cpp     2024-09-12 
21:14:33.000000000 +0200
@@ -65,22 +65,20 @@
 template <typename TStream>
 void seek(TStream& stream, ssize_t pos, SeekDirection direction)
 {
-    ios_base::seekdir seekdir;
     switch (direction)
     {
         case SeekDirection::Begin:
-            seekdir = ios_base::beg;
+            (void)utls::stream_helper<TStream>::seek(stream, 
(std::streampos)pos, ios_base::beg);
             break;
         case SeekDirection::Current:
-            seekdir = ios_base::cur;
+            (void)utls::stream_helper<TStream>::seek(stream, 
(std::streampos)pos, ios_base::cur);
             break;
         case SeekDirection::End:
-            seekdir = ios_base::end;
+            (void)utls::stream_helper<TStream>::seek(stream, 
(std::streampos)pos, ios_base::end);
             break;
         default:
             PODOFO_RAISE_ERROR(PdfErrorCode::InvalidEnumValue);
     }
-    (void)utls::stream_helper<TStream>::seek(stream, (std::streampos)pos, 
seekdir);
 }
 
 StreamDevice::StreamDevice(DeviceAccess access)
@@ -190,13 +188,13 @@
     switch (GetAccess())
     {
         case DeviceAccess::Read:
+        case DeviceAccess::ReadWrite: // We just take the input stream as the 
reference
         {
             PODOFO_INVARIANT(m_istream != nullptr);
             ret = getLength(*m_istream);
             break;
         }
         case DeviceAccess::Write:
-        case DeviceAccess::ReadWrite:
         {
             PODOFO_INVARIANT(m_ostream != nullptr);
             ret = getLength(*m_ostream);
@@ -218,13 +216,13 @@
     switch (GetAccess())
     {
         case DeviceAccess::Read:
+        case DeviceAccess::ReadWrite: // We just take the input stream as the 
reference
         {
             PODOFO_INVARIANT(m_istream != nullptr);
             ret = getPosition(*m_istream);
             break;
         }
         case DeviceAccess::Write:
-        case DeviceAccess::ReadWrite:
         {
             PODOFO_INVARIANT(m_ostream != nullptr);
             ret = getPosition(*m_ostream);
@@ -252,10 +250,42 @@
 
 void StandardStreamDevice::writeBuffer(const char* buffer, size_t size)
 {
-    PODOFO_INVARIANT(m_ostream != nullptr);
-    m_ostream->write(buffer, size);
-    if (m_ostream->fail())
-        PODOFO_RAISE_ERROR_INFO(PdfErrorCode::InvalidDeviceOperation, "Failed 
to write the given buffer");
+    switch (GetAccess())
+    {
+        case DeviceAccess::Write:
+        {
+            PODOFO_INVARIANT(m_ostream != nullptr);
+            m_ostream->write(buffer, size);
+            if (m_ostream->fail())
+                PODOFO_RAISE_ERROR_INFO(PdfErrorCode::InvalidDeviceOperation, 
"Failed to write the given buffer");
+            break;
+        }
+        case DeviceAccess::ReadWrite:
+        {
+            PODOFO_INVARIANT(m_ostream != nullptr && m_istream != nullptr);
+            // Since some iostreams such as std::stringstream have different 
position
+            // indicators for input and output sequences. Synchronize the 
ostream
+            // position indicator with the istream (the reference one) before 
writing
+            // NOTE: Some c++ libraries don't reset eofbit prior seeking
+            auto pos = getPosition(*m_istream);
+            m_Stream->clear(m_Stream->rdstate() & ~ios_base::eofbit);
+            ::seek(*m_ostream, (ssize_t)pos, SeekDirection::Begin);
+            m_ostream->write(buffer, size);
+            if (m_ostream->fail())
+                goto Fail;
+
+            // After writing, finally synchronize the istream position 
indicator
+            ::seek(*m_istream, (ssize_t)(pos + size), SeekDirection::Begin);
+            if (m_istream->fail())
+                goto Fail;
+
+            break;
+
+        Fail:
+            PODOFO_RAISE_ERROR_INFO(PdfErrorCode::InvalidDeviceOperation, 
"Failed to write the given buffer");
+            break;
+        }
+    }
 }
 
 void StandardStreamDevice::flush()
@@ -319,20 +349,30 @@
 {
     // NOTE: Some c++ libraries don't reset eofbit prior seeking
     m_Stream->clear(m_Stream->rdstate() & ~ios_base::eofbit);
-    if ((GetAccess() & DeviceAccess::Read) != DeviceAccess{ })
-    {
-        PODOFO_INVARIANT(m_istream != nullptr);
-        ::seek(*m_istream, offset, direction);
-    }
-
-    if ((GetAccess() & DeviceAccess::Write) != DeviceAccess{ })
+    switch (GetAccess())
     {
-        PODOFO_INVARIANT(m_ostream != nullptr);
-        ::seek(*m_ostream, offset, direction);
+        case DeviceAccess::Read:
+        case DeviceAccess::ReadWrite:
+        {
+            PODOFO_INVARIANT(m_istream != nullptr);
+            ::seek(*m_istream, offset, direction);
+            break;
+        }
+        case DeviceAccess::Write:
+        {
+            PODOFO_INVARIANT(m_ostream != nullptr);
+            ::seek(*m_ostream, offset, direction);
+            break;
+        }
     }
 
     if (m_Stream->fail())
-        PODOFO_RAISE_ERROR_INFO(PdfErrorCode::InvalidDeviceOperation, "Failed 
to seek to given position in the stream");
+        goto Fail;
+
+    return;
+
+Fail:
+    PODOFO_RAISE_ERROR_INFO(PdfErrorCode::InvalidDeviceOperation, "Failed to 
seek to given position in the stream");
 }
 
 FileStreamDevice::FileStreamDevice(const string_view& filepath)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podofo-0.10.3/src/podofo/auxiliary/StreamDevice.h 
new/podofo-0.10.4/src/podofo/auxiliary/StreamDevice.h
--- old/podofo-0.10.3/src/podofo/auxiliary/StreamDevice.h       2023-11-28 
10:23:37.000000000 +0100
+++ new/podofo-0.10.4/src/podofo/auxiliary/StreamDevice.h       2024-09-12 
21:14:33.000000000 +0200
@@ -135,9 +135,15 @@
         m_container(&container),
         m_Position(ate ? container.size() : 0) { }
 
+    /**
+     * \remarks by default it set the current position at the begin of the 
container
+     */
     ContainerStreamDevice(const TContainer& container) :
         ContainerStreamDevice(const_cast<TContainer&>(container), 
DeviceAccess::Read, false) { }
 
+    /**
+     * \remarks by default it set the current position at the end of the 
container 
+     */
     ContainerStreamDevice(TContainer& container) :
         ContainerStreamDevice(container, DeviceAccess::ReadWrite, true) { }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podofo-0.10.3/src/podofo/auxiliary/span.hpp 
new/podofo-0.10.4/src/podofo/auxiliary/span.hpp
--- old/podofo-0.10.3/src/podofo/auxiliary/span.hpp     2023-11-28 
10:23:37.000000000 +0100
+++ new/podofo-0.10.4/src/podofo/auxiliary/span.hpp     2024-09-12 
21:14:33.000000000 +0200
@@ -27,6 +27,7 @@
 #ifndef TCB_SPAN_NO_EXCEPTIONS
 #include <cstdio>
 #include <stdexcept>
+#include <exception>
 #endif
 
 // Various feature test macros
@@ -339,23 +340,23 @@
     constexpr span(element_type (&arr)[N]) noexcept : storage_(arr, N)
     {}
 
-    template <std::size_t N, std::size_t E = Extent,
+    template <typename T, std::size_t N, std::size_t E = Extent,
               typename std::enable_if<
                   (E == dynamic_extent || N == E) &&
                       detail::is_container_element_type_compatible<
-                          std::array<value_type, N>&, ElementType>::value,
+                          std::array<T, N>&, ElementType>::value,
                   int>::type = 0>
-    TCB_SPAN_ARRAY_CONSTEXPR span(std::array<value_type, N>& arr) noexcept
+    TCB_SPAN_ARRAY_CONSTEXPR span(std::array<T, N>& arr) noexcept
         : storage_(arr.data(), N)
     {}
 
-    template <std::size_t N, std::size_t E = Extent,
+    template <typename T, std::size_t N, std::size_t E = Extent,
               typename std::enable_if<
                   (E == dynamic_extent || N == E) &&
                       detail::is_container_element_type_compatible<
-                          const std::array<value_type, N>&, 
ElementType>::value,
+                          const std::array<T, N>&, ElementType>::value,
                   int>::type = 0>
-    TCB_SPAN_ARRAY_CONSTEXPR span(const std::array<value_type, N>& arr) 
noexcept
+    TCB_SPAN_ARRAY_CONSTEXPR span(const std::array<T, N>& arr) noexcept
         : storage_(arr.data(), N)
     {}
 
@@ -385,7 +386,8 @@
 
     template <typename OtherElementType, std::size_t OtherExtent,
               typename std::enable_if<
-                  (Extent == OtherExtent || Extent == dynamic_extent) &&
+                  (Extent == dynamic_extent || OtherExtent == dynamic_extent ||
+                   Extent == OtherExtent) &&
                       std::is_convertible<OtherElementType (*)[],
                                           ElementType (*)[]>::value,
                   int>::type = 0>
@@ -518,7 +520,8 @@
 span(const std::array<T, N>&)->span<const T, N>;
 
 template <class Container>
-span(Container&)->span<typename Container::value_type>;
+span(Container&)->span<typename std::remove_reference<
+    decltype(*detail::data(std::declval<Container&>()))>::type>;
 
 template <class Container>
 span(const Container&)->span<const typename Container::value_type>;
@@ -552,7 +555,9 @@
 }
 
 template <typename Container>
-constexpr span<typename Container::value_type> make_span(Container& cont)
+constexpr span<typename std::remove_reference<
+    decltype(*detail::data(std::declval<Container&>()))>::type>
+make_span(Container& cont)
 {
     return {cont};
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podofo-0.10.3/src/podofo/main/PdfCIDToGIDMap.cpp 
new/podofo-0.10.4/src/podofo/main/PdfCIDToGIDMap.cpp
--- old/podofo-0.10.3/src/podofo/main/PdfCIDToGIDMap.cpp        2023-11-28 
10:23:37.000000000 +0100
+++ new/podofo-0.10.4/src/podofo/main/PdfCIDToGIDMap.cpp        2024-09-12 
21:14:33.000000000 +0200
@@ -25,7 +25,7 @@
     auto buffer = cidToGidMapObj.MustGetStream().GetCopy();
     for (unsigned i = 0, count = (unsigned)buffer.size() / 2; i < count; i++)
     {
-        unsigned gid = (unsigned)buffer[i * 2 + 0] << 8 | (unsigned)buffer[i * 
2 + 1];
+        unsigned gid = (unsigned)((uint8_t)buffer[i * 2 + 0] << 8 | 
(uint8_t)buffer[i * 2 + 1]);
         map[i] = gid;
     }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podofo-0.10.3/src/podofo/main/PdfCommon.cpp 
new/podofo-0.10.4/src/podofo/main/PdfCommon.cpp
--- old/podofo-0.10.3/src/podofo/main/PdfCommon.cpp     2023-11-28 
10:23:37.000000000 +0100
+++ new/podofo-0.10.4/src/podofo/main/PdfCommon.cpp     2024-09-12 
21:14:33.000000000 +0200
@@ -11,6 +11,21 @@
 using namespace std;
 using namespace PoDoFo;
 
+// Default stack sizes
+// Windows: 1MB on x32, x64, ARM 
https://docs.microsoft.com/en-us/cpp/build/reference/stack-stack-allocations?view=msvc-160
+// Windows IIS: 512 KB for 64-bit worker processes, 256 KB for 32-bit worker 
processes
+// macOS: 8MB on main thread, 512KB on secondary threads 
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Multithreading/CreatingThreads/CreatingThreads.html
+// iOS: 1MB on main thread, 512KB on secondary threads
+// Modern Linux distros: usually 8MB on main and secondary threads (but 
setting ulimit RLIMIT_STACK to unlimited *reduces* the secondary stack size on 
most architectures: see 
https://man7.org/linux/man-pages/man3/pthread_create.3.html#NOTES )
+// the amount allocated on stack for local variables and function parameters 
varies between x86 and x64
+// in x86 pointers are 32-bit but all function parameters are on stack
+// in x64 pointers are 64-bit but first 4 function params are passed in 
registers
+// the biggest difference is between debug and non-debug stacks: a debug stack 
frame can be around 3x larger
+// due to instrumentation like ASAN which put guard bytes around stack 
variables to detect buffer overflows
+constexpr unsigned MaxRecursionDepthDefault = 450;
+
+PODOFO_EXPORT unsigned s_MaxRecursionDepth = MaxRecursionDepthDefault;
+
 #ifdef DEBUG
 PODOFO_EXPORT PdfLogSeverity s_MaxLogSeverity = PdfLogSeverity::Debug;
 #else
@@ -43,3 +58,13 @@
 {
     return logSeverity <= s_MaxLogSeverity;
 }
+
+void PdfCommon::SetMaxRecursionDepth(unsigned maxRecursionDepth)
+{
+    s_MaxRecursionDepth = maxRecursionDepth;
+}
+
+unsigned PdfCommon::GetMaxRecursionDepth()
+{
+    return s_MaxRecursionDepth;
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podofo-0.10.3/src/podofo/main/PdfCommon.h 
new/podofo-0.10.4/src/podofo/main/PdfCommon.h
--- old/podofo-0.10.3/src/podofo/main/PdfCommon.h       2023-11-28 
10:23:37.000000000 +0100
+++ new/podofo-0.10.4/src/podofo/main/PdfCommon.h       2024-09-12 
21:14:33.000000000 +0200
@@ -33,6 +33,11 @@
      */
     static PdfLogSeverity GetMaxLoggingSeverity();
 
+    // set maximum recursion depth (set to 0 to disable recursion check)
+    static void SetMaxRecursionDepth(unsigned maxRecursionDepth);
+
+    static unsigned GetMaxRecursionDepth();
+
     /** The if the given logging severity enabled or not
      */
     static bool IsLoggingSeverityEnabled(PdfLogSeverity logSeverity);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podofo-0.10.3/src/podofo/main/PdfImage.cpp 
new/podofo-0.10.4/src/podofo/main/PdfImage.cpp
--- old/podofo-0.10.3/src/podofo/main/PdfImage.cpp      2023-11-28 
10:23:37.000000000 +0100
+++ new/podofo-0.10.4/src/podofo/main/PdfImage.cpp      2024-09-12 
21:14:33.000000000 +0200
@@ -385,7 +385,7 @@
         GetObject().GetOrCreateStream().SetData(stream, info.Filters, true);
 }
 
-void PdfImage::Load(const string_view& filepath)
+void PdfImage::Load(const string_view& filepath, unsigned imageIndex)
 {
     if (filepath.length() > 3)
     {
@@ -395,7 +395,7 @@
 #ifdef PODOFO_HAVE_TIFF_LIB
         if (extension == ".tif" || extension == ".tiff")
         {
-            loadFromTiff(filepath);
+            loadFromTiff(filepath, imageIndex);
             return;
         }
 #endif
@@ -420,7 +420,7 @@
     PODOFO_RAISE_ERROR_INFO(PdfErrorCode::UnsupportedImageFormat, filepath);
 }
 
-void PdfImage::LoadFromBuffer(const bufferview& buffer)
+void PdfImage::LoadFromBuffer(const bufferview& buffer, unsigned imageIndex)
 {
     if (buffer.size() <= 4)
         return;
@@ -438,7 +438,7 @@
             magic[2] == 0x2A &&
             magic[3] == 0x00))
     {
-        loadFromTiffData((const unsigned char*)buffer.data(), buffer.size());
+        loadFromTiffData((const unsigned char*)buffer.data(), buffer.size(), 
imageIndex);
         return;
     }
 #endif
@@ -651,7 +651,7 @@
     // Do nothing
 }
 
-void PdfImage::loadFromTiffHandle(void* handle)
+void PdfImage::loadFromTiffHandle(void* handle, unsigned imageIndex)
 {
     TIFF* hInTiffHandle = (TIFF*)handle;
 
@@ -662,6 +662,9 @@
     uint16_t planarConfig, photoMetric, orientation;
     int32_t resolutionUnit;
 
+    // Set the page/image index in the tiff context
+    TIFFSetDirectory(hInTiffHandle, (uint16)imageIndex);
+
     TIFFGetField(hInTiffHandle, TIFFTAG_IMAGEWIDTH, &width);
     TIFFGetField(hInTiffHandle, TIFFTAG_IMAGELENGTH, &height);
     TIFFGetFieldDefaulted(hInTiffHandle, TIFFTAG_BITSPERSAMPLE, 
&bitsPerSample);
@@ -684,22 +687,10 @@
 
     // TODO: implement special cases
     if (TIFFIsTiled(hInTiffHandle))
-    {
-        TIFFClose(hInTiffHandle);
         PODOFO_RAISE_ERROR(PdfErrorCode::UnsupportedImageFormat);
-    }
 
     if (planarConfig != PLANARCONFIG_CONTIG && colorChannels != 1)
-    {
-        TIFFClose(hInTiffHandle);
         PODOFO_RAISE_ERROR(PdfErrorCode::UnsupportedImageFormat);
-    }
-
-    if (orientation != ORIENTATION_TOPLEFT)
-    {
-        TIFFClose(hInTiffHandle);
-        PODOFO_RAISE_ERROR(PdfErrorCode::UnsupportedImageFormat);
-    }
 
     PdfImageInfo info;
     info.Width = width;
@@ -715,6 +706,7 @@
                 decode.insert(decode.end(), 
PdfObject(static_cast<int64_t>(0)));
                 decode.insert(decode.end(), 
PdfObject(static_cast<int64_t>(1)));
                 info.Decode = std::move(decode);
+                info.ColorSpace = PdfColorSpace::DeviceGray;
             }
             else if (bitsPixel == 8 || bitsPixel == 16)
             {
@@ -722,7 +714,6 @@
             }
             else
             {
-                TIFFClose(hInTiffHandle);
                 PODOFO_RAISE_ERROR(PdfErrorCode::UnsupportedImageFormat);
             }
             break;
@@ -735,6 +726,7 @@
                 decode.insert(decode.end(), 
PdfObject(static_cast<int64_t>(1)));
                 decode.insert(decode.end(), 
PdfObject(static_cast<int64_t>(0)));
                 info.Decode = std::move(decode);
+                info.ColorSpace = PdfColorSpace::DeviceGray;
             }
             else if (bitsPixel == 8 || bitsPixel == 16)
             {
@@ -742,7 +734,6 @@
             }
             else
             {
-                TIFFClose(hInTiffHandle);
                 PODOFO_RAISE_ERROR(PdfErrorCode::UnsupportedImageFormat);
             }
             break;
@@ -750,20 +741,16 @@
         case PHOTOMETRIC_RGB:
         {
             if (bitsPixel != 24)
-            {
-                TIFFClose(hInTiffHandle);
                 PODOFO_RAISE_ERROR(PdfErrorCode::UnsupportedImageFormat);
-            }
+
             info.ColorSpace = PdfColorSpace::DeviceRGB;
             break;
         }
         case PHOTOMETRIC_SEPARATED:
         {
             if (bitsPixel != 32)
-            {
-                TIFFClose(hInTiffHandle);
                 PODOFO_RAISE_ERROR(PdfErrorCode::UnsupportedImageFormat);
-            }
+
             info.ColorSpace = PdfColorSpace::DeviceCMYK;
             break;
         }
@@ -806,7 +793,6 @@
 
         default:
         {
-            TIFFClose(hInTiffHandle);
             PODOFO_RAISE_ERROR(PdfErrorCode::UnsupportedImageFormat);
             break;
         }
@@ -821,7 +807,6 @@
             &buffer[row * scanlineSize],
             row) == (-1))
         {
-            TIFFClose(hInTiffHandle);
             PODOFO_RAISE_ERROR(PdfErrorCode::UnsupportedImageFormat);
         }
     }
@@ -830,7 +815,7 @@
     SetDataRaw(input, info);
 }
 
-void PdfImage::loadFromTiff(const string_view& filename)
+void PdfImage::loadFromTiff(const string_view& filename, unsigned imageIndex)
 {
     TIFFSetErrorHandler(TIFFErrorWarningHandler);
     TIFFSetWarningHandler(TIFFErrorWarningHandler);
@@ -850,7 +835,7 @@
 
     try
     {
-        loadFromTiffHandle(hInfile);
+        loadFromTiffHandle(hInfile, imageIndex);
     }
     catch (...)
     {
@@ -968,7 +953,7 @@
 {
     return;
 };
-void PdfImage::loadFromTiffData(const unsigned char* data, size_t len)
+void PdfImage::loadFromTiffData(const unsigned char* data, size_t len, 
unsigned imageIndex)
 {
     TIFFSetErrorHandler(TIFFErrorWarningHandler);
     TIFFSetWarningHandler(TIFFErrorWarningHandler);
@@ -983,7 +968,17 @@
     if (hInHandle == nullptr)
         PODOFO_RAISE_ERROR(PdfErrorCode::InvalidHandle);
 
-    loadFromTiffHandle(hInHandle);
+    try
+    {
+        loadFromTiffHandle(hInHandle, imageIndex);
+    }
+    catch (...)
+    {
+        TIFFClose(hInHandle);
+        throw;
+    }
+
+    TIFFClose(hInHandle);
 }
 
 #endif // PODOFO_HAVE_TIFF_LIB
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podofo-0.10.3/src/podofo/main/PdfImage.h 
new/podofo-0.10.4/src/podofo/main/PdfImage.h
--- old/podofo-0.10.3/src/podofo/main/PdfImage.h        2023-11-28 
10:23:37.000000000 +0100
+++ new/podofo-0.10.4/src/podofo/main/PdfImage.h        2024-09-12 
21:14:33.000000000 +0200
@@ -131,13 +131,17 @@
      */
     void SetDataRaw(InputStream& stream, const PdfImageInfo& info);
 
-    /** Load the image data from a file
+    /** Load the image data from bytes
+     * \param imageIndex image index to be fed to multi image/page
+     *   formats (eg. TIFF). Ignored by the other formats
      */
-    void Load(const std::string_view& filepath);
+    void Load(const std::string_view& filepath, unsigned imageIndex = 0);
 
     /** Load the image data from bytes
+     * \param imageIndex image index to be fed to multi image/page
+     *   formats (eg. TIFF). Ignored by the other formats
      */
-    void LoadFromBuffer(const bufferview& buffer);
+    void LoadFromBuffer(const bufferview& buffer, unsigned imageIndex = 0);
 
     void ExportTo(charbuff& buff, PdfExportFormat format, PdfArray args = {}) 
const;
 
@@ -188,17 +192,17 @@
 #endif // PODOFO_HAVE_JPEG_LIB
 
 #ifdef PODOFO_HAVE_TIFF_LIB
-    void loadFromTiffHandle(void* handle);
+    void loadFromTiffHandle(void* handle, unsigned imageIndex);
     /** Load the image data from a TIFF file
      *  \param filename
      */
-    void loadFromTiff(const std::string_view& filename);
+    void loadFromTiff(const std::string_view& filename, unsigned imageIndex);
 
     /** Load the image data from TIFF bytes
      *  \param data TIFF bytes
      *  \param len number of bytes
      */
-    void loadFromTiffData(const unsigned char* data, size_t len);
+    void loadFromTiffData(const unsigned char* data, size_t len, unsigned 
imageIndex);
 #endif // PODOFO_HAVE_TIFF_LIB
 
 #ifdef PODOFO_HAVE_PNG_LIB
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podofo-0.10.3/src/podofo/main/PdfPainter.cpp 
new/podofo-0.10.4/src/podofo/main/PdfPainter.cpp
--- old/podofo-0.10.3/src/podofo/main/PdfPainter.cpp    2023-11-28 
10:23:37.000000000 +0100
+++ new/podofo-0.10.4/src/podofo/main/PdfPainter.cpp    2024-09-12 
21:14:33.000000000 +0200
@@ -479,6 +479,18 @@
             this->drawTextAligned(line, x, y, width, hAlignment, style);
 
         x = 0;
+        switch (hAlignment)
+        {
+            default:
+            case PdfHorizontalAlignment::Left:
+                break;
+            case PdfHorizontalAlignment::Center:
+                x = -(width - textState.Font->GetStringLength(line, 
textState)) / 2.0;
+                break;
+            case PdfHorizontalAlignment::Right:
+                x = -(width - textState.Font->GetStringLength(line, 
textState));
+                break;
+        }
         y = -font.GetLineSpacing(textState);
     }
     PoDoFo::WriteOperator_ET(m_stream);
@@ -1200,11 +1212,8 @@
 
 void PdfGraphicsStateWrapper::SetCurrentMatrix(const Matrix& matrix)
 {
-    if (m_state->CTM == matrix)
-        return;
-
-    m_state->CTM = matrix;
-    m_painter->SetTransformationMatrix(m_state->CTM);
+    m_state->CTM = matrix * m_state->CTM;
+    m_painter->SetTransformationMatrix(matrix);
 }
 
 void PdfGraphicsStateWrapper::SetLineWidth(double lineWidth)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podofo-0.10.3/src/podofo/main/PdfParser.cpp 
new/podofo-0.10.4/src/podofo/main/PdfParser.cpp
--- old/podofo-0.10.3/src/podofo/main/PdfParser.cpp     2023-11-28 
10:23:37.000000000 +0100
+++ new/podofo-0.10.4/src/podofo/main/PdfParser.cpp     2024-09-12 
21:14:33.000000000 +0200
@@ -238,11 +238,6 @@
 
     if (trailer->GetDictionary().HasKey("XRefStm"))
     {
-        // Whenever we read a XRefStm key, 
-        // we know that the file was updated.
-        if (!trailer->GetDictionary().HasKey("Prev"))
-            m_IncrementalUpdateCount++;
-
         try
         {
             ReadXRefStreamContents(device, 
static_cast<size_t>(trailer->GetDictionary().FindKeyAs<int64_t>("XRefStm", 0)), 
false);
@@ -265,19 +260,11 @@
             // we know that the file was updated.
             m_IncrementalUpdateCount++;
 
-            try
-            {
-                if (m_visitedXRefOffsets.find((size_t)offset) == 
m_visitedXRefOffsets.end())
-                    ReadXRefContents(device, (size_t)offset);
-                else
-                    PoDoFo::LogMessage(PdfLogSeverity::Warning, "XRef contents 
at offset {} requested twice, skipping the second read",
-                        static_cast<int64_t>(offset));
-            }
-            catch (PdfError& e)
-            {
-                PODOFO_PUSH_FRAME_INFO(e, "Unable to load /Prev xref entries");
-                throw e;
-            }
+            if (m_visitedXRefOffsets.find((size_t)offset) == 
m_visitedXRefOffsets.end())
+                ReadXRefContents(device, (size_t)offset, false);
+            else
+                PoDoFo::LogMessage(PdfLogSeverity::Warning, "XRef contents at 
offset {} requested twice, skipping the second read",
+                    static_cast<int64_t>(offset));
         }
         else
         {
@@ -410,18 +397,7 @@
         }
     }
 
-    try
-    {
-        readNextTrailer(device);
-    }
-    catch (PdfError& e)
-    {
-        if (e != PdfErrorCode::NoTrailer)
-        {
-            PODOFO_PUSH_FRAME(e);
-            throw e;
-        }
-    }
+    readNextTrailer(device);
 }
 
 bool CheckEOL(char e1, char e2)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podofo-0.10.3/src/podofo/main/PdfWriter.cpp 
new/podofo-0.10.4/src/podofo/main/PdfWriter.cpp
--- old/podofo-0.10.3/src/podofo/main/PdfWriter.cpp     2023-11-28 
10:23:37.000000000 +0100
+++ new/podofo-0.10.4/src/podofo/main/PdfWriter.cpp     2024-09-12 
21:14:33.000000000 +0200
@@ -290,7 +290,7 @@
     info->Write(length, m_WriteFlags, nullptr, m_buffer);
 
     charbuff buffer(length.GetLength());
-    StringStreamDevice device(buffer);
+    StringStreamDevice device(buffer, DeviceAccess::Write, false);
     info->Write(device, m_WriteFlags, nullptr, m_buffer);
 
     // calculate the MD5 Sum
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/podofo-0.10.3/src/podofo/private/PdfDeclarationsPrivate.cpp 
new/podofo-0.10.4/src/podofo/private/PdfDeclarationsPrivate.cpp
--- old/podofo-0.10.3/src/podofo/private/PdfDeclarationsPrivate.cpp     
2023-11-28 10:23:37.000000000 +0100
+++ new/podofo-0.10.4/src/podofo/private/PdfDeclarationsPrivate.cpp     
2024-09-12 21:14:33.000000000 +0200
@@ -28,25 +28,12 @@
 
 constexpr unsigned BUFFER_SIZE = 4096;
 
-// Default stack sizes
-// Windows: 1MB on x32, x64, ARM 
https://docs.microsoft.com/en-us/cpp/build/reference/stack-stack-allocations?view=msvc-160
-// Windows IIS: 512 KB for 64-bit worker processes, 256 KB for 32-bit worker 
processes
-// macOS: 8MB on main thread, 512KB on secondary threads 
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Multithreading/CreatingThreads/CreatingThreads.html
-// iOS: 1MB on main thread, 512KB on secondary threads
-// Modern Linux distros: usually 8MB on main and secondary threads (but 
setting ulimit RLIMIT_STACK to unlimited *reduces* the secondary stack size on 
most architectures: see 
https://man7.org/linux/man-pages/man3/pthread_create.3.html#NOTES )
-// the amount allocated on stack for local variables and function parameters 
varies between x86 and x64
-// in x86 pointers are 32-bit but all function parameters are on stack
-// in x64 pointers are 64-bit but first 4 function params are passed in 
registers
-// the biggest difference is between debug and non-debug stacks: a debug stack 
frame can be around 3x larger
-// due to instrumentation like ASAN which put guard bytes around stack 
variables to detect buffer overflows
-constexpr unsigned MaxRecursionDepthDefault = 256;
-
-static unsigned s_MaxRecursionDepth = MaxRecursionDepthDefault;
 thread_local unsigned s_recursionDepth = 0;
 
 static const locale s_cachedLocale("C");
 
 extern PODOFO_IMPORT PdfLogSeverity s_MaxLogSeverity;
+extern PODOFO_IMPORT unsigned s_MaxRecursionDepth;
 extern PODOFO_IMPORT LogMessageCallback s_LogMessageCallback;
 
 static char getEscapedCharacter(char ch);
@@ -1420,16 +1407,6 @@
     Exit();
 }
 
-void utls::RecursionGuard::SetMaxRecursionDepth(unsigned maxRecursionDepth)
-{
-    s_MaxRecursionDepth = maxRecursionDepth;
-}
-
-unsigned utls::RecursionGuard::GetMaxRecursionDepth()
-{
-    return s_MaxRecursionDepth;
-}
-
 void removeTrailingZeroes(string& str)
 {
     // Remove trailing zeroes
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/podofo-0.10.3/src/podofo/private/PdfDeclarationsPrivate.h 
new/podofo-0.10.4/src/podofo/private/PdfDeclarationsPrivate.h
--- old/podofo-0.10.3/src/podofo/private/PdfDeclarationsPrivate.h       
2023-11-28 10:23:37.000000000 +0100
+++ new/podofo-0.10.4/src/podofo/private/PdfDeclarationsPrivate.h       
2024-09-12 21:14:33.000000000 +0200
@@ -216,11 +216,6 @@
         RecursionGuard();
         ~RecursionGuard();
 
-        // set maximum recursion depth (set to 0 to disable recursion check)
-        static void SetMaxRecursionDepth(unsigned maxRecursionDepth);
-
-        static unsigned GetMaxRecursionDepth();
-
     private:
         void Enter();
         void Exit();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podofo-0.10.3/src/podofo/private/charconv_compat.h 
new/podofo-0.10.4/src/podofo/private/charconv_compat.h
--- old/podofo-0.10.3/src/podofo/private/charconv_compat.h      2023-11-28 
10:23:37.000000000 +0100
+++ new/podofo-0.10.4/src/podofo/private/charconv_compat.h      2024-09-12 
21:14:33.000000000 +0200
@@ -7,7 +7,7 @@
 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 10
 #define WANT_CHARS_FORMAT
 #endif
-#if (defined(__GNUC__) && __GNUC__ < 11) || defined(__clang__)
+#if (defined(__GNUC__) && !defined(__MINGW32__) &&  __GNUC__ < 11) || 
(defined(__MINGW32__) &&  __GNUC__ < 12) || defined(__clang__)
 #define WANT_FROM_CHARS
 #endif
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podofo-0.10.3/test/unit/ImageTest.cpp 
new/podofo-0.10.4/test/unit/ImageTest.cpp
--- old/podofo-0.10.3/test/unit/ImageTest.cpp   2023-11-28 10:23:37.000000000 
+0100
+++ new/podofo-0.10.4/test/unit/ImageTest.cpp   2024-09-12 21:14:33.000000000 
+0200
@@ -38,7 +38,7 @@
     PdfMemDocument doc;
     doc.Load(TestUtils::GetTestInputFilePath("Hierarchies1.pdf"));
     // Try to extract jpeg image
-    auto imageObj = doc.GetObjects().GetObject(PdfReference(36, 0));
+    auto imageObj = doc.GetObjects().GetObject(PdfReference(156, 0));
     charbuff buffer;
 
     // Unpacking directly the stream shall throw since it has jpeg content
@@ -99,7 +99,7 @@
         painter.SetCanvas(page);
         auto img = doc.CreateImage();
         img->Load(TestUtils::GetTestInputFilePath("ReferenceImage.png"));
-        painter.DrawImage(*img.get(), 50.0, 50.0);
+        painter.DrawImage(*img, 50.0, 50.0);
         painter.FinishDrawing();
         doc.Save(outputFile);
     }
@@ -185,3 +185,25 @@
         
TestUtils::WriteTestOutputFile(TestUtils::GetTestOutputFilePath("YCCK-jpeg.ppm"),
 ppmbuffer);
     }
 }
+
+TEST_CASE("TestImage7")
+{
+    auto outputFile = TestUtils::GetTestOutputFilePath("TestImage7.pdf");
+    {
+        PdfMemDocument doc;
+        PdfPainter painter;
+        auto& page = 
doc.GetPages().CreatePage(PdfPage::CreateStandardPageSize(PdfPageSize::A4));
+        painter.SetCanvas(page);
+
+        auto img1 = doc.CreateImage();
+        img1->Load(TestUtils::GetTestInputFilePath("MultipleFormats.tif"));
+        painter.DrawImage(*img1, 50, 700, 0.5, 0.5);
+
+        auto img2 = doc.CreateImage();
+        img2->Load(TestUtils::GetTestInputFilePath("MultipleFormats.tif"), 8);
+        painter.DrawImage(*img2, 50, 600, 0.5, 0.5);
+
+        painter.FinishDrawing();
+        doc.Save(outputFile);
+    }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/podofo-0.10.3/test/unit/ParserTest.cpp 
new/podofo-0.10.4/test/unit/ParserTest.cpp
--- old/podofo-0.10.3/test/unit/ParserTest.cpp  2023-11-28 10:23:37.000000000 
+0100
+++ new/podofo-0.10.4/test/unit/ParserTest.cpp  2024-09-12 21:14:33.000000000 
+0200
@@ -166,7 +166,7 @@
     }
     catch (PdfError& error)
     {
-        REQUIRE(error.GetCode() == PdfErrorCode::InvalidXRef);
+        REQUIRE(error.GetCode() == PdfErrorCode::NoTrailer);
     }
     catch (exception&)
     {
@@ -204,7 +204,7 @@
     }
     catch (PdfError& error)
     {
-        REQUIRE(error.GetCode() == PdfErrorCode::InvalidXRef);
+        REQUIRE(error.GetCode() == PdfErrorCode::NoTrailer);
     }
     catch (exception&)
     {
@@ -2707,6 +2707,21 @@
     }
 }
 
+TEST_CASE("TestManyTrailer")
+{
+    try
+    {
+        PdfCommon::SetMaxRecursionDepth(256);
+        PdfMemDocument doc;
+        doc.Load(TestUtils::GetTestInputFilePath("Empty160trailer.pdf"));
+    }
+    catch (PdfError&)
+    {
+        return;
+    }
+    FAIL("Should fail with stack overflow");
+}
+
 string generateXRefEntries(size_t count)
 {
     string strXRefEntries;

++++++ podofo-CVE-2019-20093.patch ++++++
>From the upstream bug report proposed fix
From: Sandro Mani 
Date: Fri, 17 Jan 2020
Subject: podofo: denial of service (NULL pointer dereference) in 
PoDoFo::PdfVariant::DelayedLoad function in PdfVariant.h
References: https://bugzilla.opensuse.org/1223437
References: https://sourceforge.net/p/podofo/tickets/75/
References: CVE-2019-20093

--- podofo-0.10.4/tools/podofoimgextract/ImageExtractor.cpp
+++ podofo-0.10.4_new/tools/podofoimgextract/ImageExtractor.cpp
@@ -88,6 +88,11 @@
         //long lBitsPerComponent = pObject->GetDictionary().GetKey( 
PdfName("BitsPerComponent" ) )->GetNumber();
         // TODO: Handle colorspaces
 
+        if ( !pObject->GetDictionary().HasKey( PdfName("Width" ) ) || 
!pObject->GetDictionary().HasKey( PdfName("Height" ) ) )
+        {
+            PODOFO_RAISE_ERROR( ePdfError_BrokenFile );
+        }
+
         // Create a ppm image
         const char* ppmHeader = "P6\n# Image extracted by PoDoFo\n%u 
%u\n%li\n";

2020-01-17 

Reply via email to