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;
}