CVE-2026-6045
authorDebian LibreOffice Maintainers <debian-openoffice@lists.debian.org>
Sat, 6 Jun 2026 20:12:08 +0000 (22:12 +0200)
committerRene Engelhard <rene@debian.org>
Sat, 6 Jun 2026 20:12:08 +0000 (22:12 +0200)
CVE-2026-6045 EMF+ Heap-buffer-overflow in EMFPBrush::Read

CVE-2026-6045 EMF+ Heap-buffer-overflow in EMFPBrush::Read
A nested format problem tucked away in the rendering path, probably
need to add something dedicated to the simpler fuzzer to force that
render path to be exercised.

From 279c7ea61829efe5cabc5832d06e1833ad28379f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= <caolan.mcnamara@collabora.com>
Date: Thu, 9 Apr 2026 20:00:38 +0100
Subject: [PATCH] check that the file can provide the claimed data

and make sure we initialize these locals

Change-Id: Ifa899e36f678216574364e5206037ab57b2d19d9
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/203577
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
Signed-off-by: Xisco Fauli <xiscofauli@libreoffice.org>
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/203628
Signed-off-by: Xisco Fauli <xiscofauli@libreoffice.org>
Gbp-Pq: Name CVE-2026-6045.diff

drawinglayer/source/tools/emfpbrush.cxx
drawinglayer/source/tools/emfppen.cxx

index 786209bb641b21cfac9262114ee85fe2a620a961..c2180ebf75168d7c0dbdb9063b352ee417842ce4 100644 (file)
@@ -63,7 +63,7 @@ namespace emfplushelper
 
     void EMFPBrush::Read(SvStream& s, EmfPlusHelperData const & rR)
     {
-        sal_uInt32 header;
+        sal_uInt32 header(0);
 
         s.ReadUInt32(header).ReadUInt32(type);
 
@@ -74,7 +74,7 @@ namespace emfplushelper
         {
             case BrushTypeSolidColor:
             {
-                sal_uInt32 color;
+                sal_uInt32 color(0);
                 s.ReadUInt32(color);
 
                 solidColor = ::Color(ColorAlpha, (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
@@ -83,9 +83,9 @@ namespace emfplushelper
             }
             case BrushTypeHatchFill:
             {
-                sal_uInt32 style;
-                sal_uInt32 foregroundColor;
-                sal_uInt32 backgroundColor;
+                sal_uInt32 style(0);
+                sal_uInt32 foregroundColor(0);
+                sal_uInt32 backgroundColor(0);
                 s.ReadUInt32(style);
                 s.ReadUInt32(foregroundColor);
                 s.ReadUInt32(backgroundColor);
@@ -107,7 +107,7 @@ namespace emfplushelper
             {
                 s.ReadUInt32(additionalFlags).ReadInt32(wrapMode);
                 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tAdditional flags: 0x" << std::hex << additionalFlags << std::dec);
-                sal_uInt32 color;
+                sal_uInt32 color(0);
                 s.ReadUInt32(color);
                 solidColor = ::Color(ColorAlpha, (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
                 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tCenter color: 0x" << std::hex << color << std::dec);
@@ -116,6 +116,12 @@ namespace emfplushelper
                 s.ReadUInt32(surroundColorsNumber);
                 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\t number of surround colors: " << surroundColorsNumber);
 
+                if (surroundColorsNumber > s.remainingSize() / sizeof(sal_uInt32))
+                {
+                    SAL_WARN("drawinglayer.emf", "EMF+\t\t\t\tTruncated surround colors");
+                    return;
+                }
+
                 surroundColors.reset( new ::Color[surroundColorsNumber] );
 
                 for (sal_uInt32 i = 0; i < surroundColorsNumber; i++)
@@ -129,15 +135,15 @@ namespace emfplushelper
 
                 if (additionalFlags & 0x01) // BrushDataPath
                 {
-                    sal_Int32 pathLength;
+                    sal_Int32 pathLength(0);
 
                     s.ReadInt32(pathLength);
                     SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tPath length: " << pathLength);
 
                     sal_uInt64 const pos = s.Tell();
 
-                    sal_uInt32 pathHeader;
-                    sal_Int32 pathPoints, pathFlags;
+                    sal_uInt32 pathHeader(0);
+                    sal_Int32 pathPoints(0), pathFlags(0);
                     s.ReadUInt32(pathHeader).ReadInt32(pathPoints).ReadInt32(pathFlags);
 
                     SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tPath (brush path gradient)");
@@ -158,7 +164,7 @@ namespace emfplushelper
                 }
                 else
                 {
-                    sal_Int32 boundaryPointCount;
+                    sal_Int32 boundaryPointCount(0);
                     s.ReadInt32(boundaryPointCount);
 
                     sal_uInt64 const pos = s.Tell();
@@ -192,6 +198,13 @@ namespace emfplushelper
                 {
                     s.ReadUInt32(blendPoints);
                     SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tuse blend, points: " << blendPoints);
+
+                    if (blendPoints > s.remainingSize() / (2 * sizeof(float)))
+                    {
+                        SAL_WARN("drawinglayer.emf", "EMF+\t\t\t\tTruncated blend points");
+                        return;
+                    }
+
                     blendPositions.reset( new float[2 * blendPoints] );
                     blendFactors = blendPositions.get() + blendPoints;
 
@@ -212,6 +225,13 @@ namespace emfplushelper
                 {
                     s.ReadUInt32(colorblendPoints);
                     SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tUse color blend, points: " << colorblendPoints);
+
+                    if (colorblendPoints > s.remainingSize() / (sizeof(float) + sizeof(sal_uInt32)))
+                    {
+                        SAL_WARN("drawinglayer.emf", "EMF+\t\t\t\tTruncated color blend points");
+                        return;
+                    }
+
                     colorblendPositions.reset( new float[colorblendPoints] );
                     colorblendColors.reset( new ::Color[colorblendPoints] );
 
@@ -238,7 +258,7 @@ namespace emfplushelper
                 s.ReadFloat(firstPointX).ReadFloat(firstPointY).ReadFloat(aWidth).ReadFloat(aHeight);
                 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tFirst gradient point: " << firstPointX << ":" << firstPointY
                                          << ", size " << aWidth << "x" << aHeight);
-                sal_uInt32 color;
+                sal_uInt32 color(0);
                 s.ReadUInt32(color);
                 solidColor = ::Color(ColorAlpha, (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
                 SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tfirst color: 0x" << std::hex << color << std::dec);
@@ -267,6 +287,13 @@ namespace emfplushelper
                 {
                     s.ReadUInt32(blendPoints);
                     SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tUse blend, points: " << blendPoints);
+
+                    if (blendPoints > s.remainingSize() / (2 * sizeof(float)))
+                    {
+                        SAL_WARN("drawinglayer.emf", "EMF+\t\t\t\tTruncated blend points");
+                        return;
+                    }
+
                     blendPositions.reset( new float[2 * blendPoints] );
                     blendFactors = blendPositions.get() + blendPoints;
 
@@ -287,6 +314,13 @@ namespace emfplushelper
                 {
                     s.ReadUInt32(colorblendPoints);
                     SAL_INFO("drawinglayer.emf", "EMF+\t\t\t\tUse color blend, points: " << colorblendPoints);
+
+                    if (colorblendPoints > s.remainingSize() / (sizeof(float) + sizeof(sal_uInt32)))
+                    {
+                        SAL_WARN("drawinglayer.emf", "EMF+\t\t\t\tTruncated color blend points");
+                        return;
+                    }
+
                     colorblendPositions.reset( new float[colorblendPoints] );
                     colorblendColors.reset( new ::Color[colorblendPoints] );
 
index aaa944660110811c6a43cd0642ef43afe2b0b9f5..112a3e4f0ff22e1864e54b165bf44211a78f52ba 100644 (file)
@@ -183,7 +183,7 @@ namespace emfplushelper
     void EMFPPen::Read(SvStream& s, EmfPlusHelperData const & rR)
     {
         sal_Int32 lineJoin = EmfPlusLineJoinTypeMiter;
-        sal_uInt32 graphicsVersion, penType;
+        sal_uInt32 graphicsVersion(0), penType(0);
         s.ReadUInt32(graphicsVersion).ReadUInt32(penType).ReadUInt32(penDataFlags).ReadUInt32(penUnit).ReadFloat(penWidth);
         SAL_INFO("drawinglayer.emf", "EMF+\t\tGraphics version: 0x" << std::hex << graphicsVersion);
         SAL_INFO("drawinglayer.emf", "EMF+\t\tType: " << penType);
@@ -248,7 +248,7 @@ namespace emfplushelper
 
         if (penDataFlags & EmfPlusPenDataMiterLimit)
         {
-            float miterLimit;
+            float miterLimit(0);
             s.ReadFloat(miterLimit);
 
             // EMF+ JoinTypeMiterClipped is working as our B2DLineJoin::Miter
@@ -302,11 +302,17 @@ namespace emfplushelper
         if (penDataFlags & EmfPlusPenDataDashedLine)
         {
             dashStyle = EmfPlusLineStyleCustom;
-            sal_uInt32 dashPatternLen;
+            sal_uInt32 dashPatternLen(0);
 
             s.ReadUInt32(dashPatternLen);
             SAL_INFO("drawinglayer.emf", "EMF+\t\t\tdashPatternLen: " << dashPatternLen);
 
+            if (dashPatternLen > s.remainingSize() / sizeof(float))
+            {
+                SAL_WARN("drawinglayer.emf", "EMF+\t\t\tTruncated dash pattern");
+                return;
+            }
+
             dashPattern.resize( dashPatternLen );
 
             for (sal_uInt32 i = 0; i < dashPatternLen; i++)
@@ -329,9 +335,15 @@ namespace emfplushelper
         if (penDataFlags & EmfPlusPenDataCompoundLine)
         {
             SAL_WARN("drawinglayer.emf", "EMF+\t\t\tTODO PenDataCompoundLine");
-            sal_uInt32 compoundArrayLen;
+            sal_uInt32 compoundArrayLen(0);
             s.ReadUInt32(compoundArrayLen);
 
+            if (compoundArrayLen > s.remainingSize() / sizeof(float))
+            {
+                SAL_WARN("drawinglayer.emf", "EMF+\t\t\tTruncated compound array");
+                return;
+            }
+
             compoundArray.resize(compoundArrayLen);
 
             for (sal_uInt32 i = 0; i < compoundArrayLen; i++)