File libEMF-1.0.7-SLE15-CVE-2020-13999-int-overflow-and-DOS.patch of Package libEMF.25624

diff --git a/libemf/libemf.cpp b/libemf/libemf.cpp
index 3d67d2c..20a9c29 100644
--- a/libemf/libemf.cpp
+++ b/libemf/libemf.cpp
@@ -1637,11 +1637,33 @@ extern "C" {
   BOOL ScaleViewportExtEx ( HDC context, INT x_num, INT x_den,
 			    INT y_num, INT y_den, LPSIZE size )
   {
+    // Avoid obvious nonsense results.
+    if ( x_num == 0 or x_den == 0 or y_num == 0 or y_den == 0 ) return FALSE;
+
     EMF::METAFILEDEVICECONTEXT* dc =
       dynamic_cast<EMF::METAFILEDEVICECONTEXT*>(EMF::globalObjects.find( context ));
 
     if ( dc == 0 ) return FALSE;
 
+    // Documentation says the numerator is computed first.
+    // Can we perform this operation? Numerator must not overflow and
+    // if it is negative, division must not overflow.
+    INT num{0};
+    if ( __builtin_smul_overflow( dc->viewport_ext.cx, x_num, &num ) ) {
+      return FALSE;
+    }
+    if ( num == INT_MIN and x_den == -1 ) {
+      return FALSE;
+    }
+    INT x_ext{ num / x_den };
+    if ( __builtin_smul_overflow( dc->viewport_ext.cy, y_num, &num ) ) {
+      return FALSE;
+    }
+    if ( num == INT_MIN and y_den == -1 ) {
+      return FALSE;
+    }
+    INT y_ext{ num / y_den };
+
     EMF::EMRSCALEVIEWPORTEXTEX* scaleviewportextex =
       new EMF::EMRSCALEVIEWPORTEXTEX( x_num, x_den, y_num, y_den );
 
@@ -1650,8 +1672,8 @@ extern "C" {
     if ( size != 0 )
       *size = dc->viewport_ext;
 
-    dc->viewport_ext.cx = dc->viewport_ext.cx * x_num / x_den;
-    dc->viewport_ext.cy = dc->viewport_ext.cy * y_num / y_den;
+    dc->viewport_ext.cx = x_ext;
+    dc->viewport_ext.cy = y_ext;
 
     return TRUE;
   }
@@ -1722,6 +1744,25 @@ extern "C" {
 
     if ( dc == 0 ) return FALSE;
 
+    // Documentation says the numerator is computed first.
+    // Can we perform this operation? Numerator must not overflow and
+    // if it is negative, division must not overflow.
+    INT num{0};
+    if ( __builtin_smul_overflow( dc->window_ext.cx, x_num, &num ) ) {
+      return FALSE;
+    }
+    if ( num == INT_MIN and x_den == -1 ) {
+      return FALSE;
+    }
+    INT x_ext{ num / x_den };
+    if ( __builtin_smul_overflow( dc->window_ext.cy, y_num, &num ) ) {
+      return FALSE;
+    }
+    if ( num == INT_MIN and y_den == -1 ) {
+      return FALSE;
+    }
+    INT y_ext{ num / y_den };
+
     EMF::EMRSCALEWINDOWEXTEX* scalewindowextex =
       new EMF::EMRSCALEWINDOWEXTEX( x_num, x_den, y_num, y_den );
 
@@ -1730,8 +1771,8 @@ extern "C" {
     if ( size != 0 )
       *size = dc->window_ext;
 
-    dc->window_ext.cx = dc->window_ext.cx * x_num / x_den;
-    dc->window_ext.cy = dc->window_ext.cy * y_num / y_den;
+    dc->window_ext.cx = x_ext;
+    dc->window_ext.cy = y_ext;
 
     return TRUE;
   }
openSUSE Build Service is sponsored by