File libEMF-1.0.7-SLE12-CVE-2020-13999-int-overflow-and-DOS.patch of Package libEMF.25625
diff --git a/libemf/libemf.cpp b/libemf/libemf.cpp
index 3d67d2c..8475f2a 100644
--- a/libemf/libemf.cpp
+++ b/libemf/libemf.cpp
@@ -23,6 +23,20 @@
#include "libemf.h"
+/* GCC 4.8 (that we are using in SLE-12) does not have '__builtin_smul_overflow'.
+ * We need to roll our own.
+ * Returns TRUE if overflow occurred.
+ */
+static bool smul_overflow(int a, int b, int *res)
+{
+ *res = a * b;
+ if ((a == 0) || (b == 0))
+ return false;
+ if (*res / a == b)
+ return false;
+ return true;
+}
+
namespace EMF {
const char PADDING::padding_[4] = { 0, 0, 0, 0 };
@@ -1637,11 +1651,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 ( 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 ( 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 +1686,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 +1758,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 ( 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 ( 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 +1785,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;
}