From: Jeff Smith whydoubt@gmail.com
1. Subtracting integers may result in an overflow or underflow. 2. Right at the 'edge' of underflowing, the result of subtraction may be INT_MIN, and the call to abs() will also result in INT_MIN.
This fix accounts for all of these conditions. --- dlls/ddraw/tests/ddraw1.c | 9 ++++++++- dlls/ddraw/tests/ddraw2.c | 9 ++++++++- dlls/ddraw/tests/ddraw4.c | 9 ++++++++- dlls/ddraw/tests/ddraw7.c | 9 ++++++++- 4 files changed, 32 insertions(+), 4 deletions(-)
diff --git a/dlls/ddraw/tests/ddraw1.c b/dlls/ddraw/tests/ddraw1.c index cde80c58e99..48ce8214180 100644 --- a/dlls/ddraw/tests/ddraw1.c +++ b/dlls/ddraw/tests/ddraw1.c @@ -54,13 +54,20 @@ static BOOL compare_float(float f, float g, unsigned int ulps) { int x = *(int *)&f; int y = *(int *)&g; + int delta;
if (x < 0) x = INT_MIN - x; if (y < 0) y = INT_MIN - y;
- if (abs(x - y) > ulps) + delta = x - y; + + /* Check for overflow and related conditions */ + if (((x ^ y) & (x ^ delta)) < 0 || delta == INT_MIN) + return FALSE; + + if (abs(delta) > ulps) return FALSE;
return TRUE; diff --git a/dlls/ddraw/tests/ddraw2.c b/dlls/ddraw/tests/ddraw2.c index 86056014f96..0b226c97d3e 100644 --- a/dlls/ddraw/tests/ddraw2.c +++ b/dlls/ddraw/tests/ddraw2.c @@ -55,13 +55,20 @@ static BOOL compare_float(float f, float g, unsigned int ulps) { int x = *(int *)&f; int y = *(int *)&g; + int delta;
if (x < 0) x = INT_MIN - x; if (y < 0) y = INT_MIN - y;
- if (abs(x - y) > ulps) + delta = x - y; + + /* Check for overflow and related conditions */ + if (((x ^ y) & (x ^ delta)) < 0 || delta == INT_MIN) + return FALSE; + + if (abs(delta) > ulps) return FALSE;
return TRUE; diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c index 4458cea5145..93ad8636a17 100644 --- a/dlls/ddraw/tests/ddraw4.c +++ b/dlls/ddraw/tests/ddraw4.c @@ -61,13 +61,20 @@ static BOOL compare_float(float f, float g, unsigned int ulps) { int x = *(int *)&f; int y = *(int *)&g; + int delta;
if (x < 0) x = INT_MIN - x; if (y < 0) y = INT_MIN - y;
- if (abs(x - y) > ulps) + delta = x - y; + + /* Check for overflow and related conditions */ + if (((x ^ y) & (x ^ delta)) < 0 || delta == INT_MIN) + return FALSE; + + if (abs(delta) > ulps) return FALSE;
return TRUE; diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c index bbb78169aea..b3a0a60af87 100644 --- a/dlls/ddraw/tests/ddraw7.c +++ b/dlls/ddraw/tests/ddraw7.c @@ -72,13 +72,20 @@ static BOOL compare_float(float f, float g, unsigned int ulps) { int x = *(int *)&f; int y = *(int *)&g; + int delta;
if (x < 0) x = INT_MIN - x; if (y < 0) y = INT_MIN - y;
- if (abs(x - y) > ulps) + delta = x - y; + + /* Check for overflow and related conditions */ + if (((x ^ y) & (x ^ delta)) < 0 || delta == INT_MIN) + return FALSE; + + if (abs(delta) > ulps) return FALSE;
return TRUE;