summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWerner Lemberg <wl@gnu.org>2017-05-28 07:20:09 +0200
committerWerner Lemberg <wl@gnu.org>2017-05-28 07:20:09 +0200
commit93572190822160f0671b32000ea6a01d9a0ffd07 (patch)
tree3e70557873f08293e2975837659178366f1e3f09
parenta9331c0f4d17a86251f7b16343af03e8055191af (diff)
downloadfreetype2-93572190822160f0671b32000ea6a01d9a0ffd07.tar.gz
Fix negation of INT_MIN and LONG_MIN (#46149).
* src/base/ftcalc.c (FT_MOVE_SIGN): Add argument to pass unsigned value, to be used as the result. (FT_MulDiv, FT_MulDiv_No_Round, FT_DivFix, FT_MulFix, FT_Vector_NormLen): Updated.
-rw-r--r--ChangeLog9
-rw-r--r--src/base/ftcalc.c73
2 files changed, 46 insertions, 36 deletions
diff --git a/ChangeLog b/ChangeLog
index f4f64d1c3..feb14f71a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2017-05-28 Werner Lemberg <wl@gnu.org>
+
+ Fix negation of INT_MIN and LONG_MIN (#46149).
+
+ * src/base/ftcalc.c (FT_MOVE_SIGN): Add argument to pass unsigned
+ value, to be used as the result.
+ (FT_MulDiv, FT_MulDiv_No_Round, FT_DivFix, FT_MulFix,
+ FT_Vector_NormLen): Updated.
+
2017-05-27 Werner Lemberg <wl@gnu.org>
[truetype] Fix handling of design coordinates (#51127).
diff --git a/src/base/ftcalc.c b/src/base/ftcalc.c
index f0525502f..b4b66e402 100644
--- a/src/base/ftcalc.c
+++ b/src/base/ftcalc.c
@@ -68,14 +68,15 @@
#define FT_COMPONENT trace_calc
- /* transfer sign leaving a positive number */
-#define FT_MOVE_SIGN( x, s ) \
- FT_BEGIN_STMNT \
- if ( x < 0 ) \
- { \
- x = -x; \
- s = -s; \
- } \
+ /* transfer sign, leaving a positive number; */
+ /* we need an unsigned value to safely negate INT_MIN (or LONG_MIN) */
+#define FT_MOVE_SIGN( x, x_unsigned, s ) \
+ FT_BEGIN_STMNT \
+ if ( x < 0 ) \
+ { \
+ x_unsigned = -x_unsigned; \
+ s = -s; \
+ } \
FT_END_STMNT
/* The following three functions are available regardless of whether */
@@ -179,14 +180,14 @@
FT_Long d_;
- FT_MOVE_SIGN( a_, s );
- FT_MOVE_SIGN( b_, s );
- FT_MOVE_SIGN( c_, s );
-
a = (FT_UInt64)a_;
b = (FT_UInt64)b_;
c = (FT_UInt64)c_;
+ FT_MOVE_SIGN( a_, a, s );
+ FT_MOVE_SIGN( b_, b, s );
+ FT_MOVE_SIGN( c_, c, s );
+
d = c > 0 ? ( a * b + ( c >> 1 ) ) / c
: 0x7FFFFFFFUL;
@@ -208,14 +209,14 @@
FT_Long d_;
- FT_MOVE_SIGN( a_, s );
- FT_MOVE_SIGN( b_, s );
- FT_MOVE_SIGN( c_, s );
-
a = (FT_UInt64)a_;
b = (FT_UInt64)b_;
c = (FT_UInt64)c_;
+ FT_MOVE_SIGN( a_, a, s );
+ FT_MOVE_SIGN( b_, b, s );
+ FT_MOVE_SIGN( c_, c, s );
+
d = c > 0 ? a * b / c
: 0x7FFFFFFFUL;
@@ -257,12 +258,12 @@
FT_Long q_;
- FT_MOVE_SIGN( a_, s );
- FT_MOVE_SIGN( b_, s );
-
a = (FT_UInt64)a_;
b = (FT_UInt64)b_;
+ FT_MOVE_SIGN( a_, a, s );
+ FT_MOVE_SIGN( b_, a, s );
+
q = b > 0 ? ( ( a << 16 ) + ( b >> 1 ) ) / b
: 0x7FFFFFFFUL;
@@ -422,14 +423,14 @@
/* XXX: this function does not allow 64-bit arguments */
- FT_MOVE_SIGN( a_, s );
- FT_MOVE_SIGN( b_, s );
- FT_MOVE_SIGN( c_, s );
-
a = (FT_UInt32)a_;
b = (FT_UInt32)b_;
c = (FT_UInt32)c_;
+ FT_MOVE_SIGN( a_, a, s );
+ FT_MOVE_SIGN( b_, b, s );
+ FT_MOVE_SIGN( c_, c, s );
+
if ( c == 0 )
a = 0x7FFFFFFFUL;
@@ -470,14 +471,14 @@
/* XXX: this function does not allow 64-bit arguments */
- FT_MOVE_SIGN( a_, s );
- FT_MOVE_SIGN( b_, s );
- FT_MOVE_SIGN( c_, s );
-
a = (FT_UInt32)a_;
b = (FT_UInt32)b_;
c = (FT_UInt32)c_;
+ FT_MOVE_SIGN( a_, a, s );
+ FT_MOVE_SIGN( b_, b, s );
+ FT_MOVE_SIGN( c_, c, s );
+
if ( c == 0 )
a = 0x7FFFFFFFUL;
@@ -575,12 +576,12 @@
/* XXX: this function does not allow 64-bit arguments */
- FT_MOVE_SIGN( a_, s );
- FT_MOVE_SIGN( b_, s );
-
a = (FT_UInt32)a_;
b = (FT_UInt32)b_;
+ FT_MOVE_SIGN( a_, a, s );
+ FT_MOVE_SIGN( b_, b, s );
+
if ( a + ( b >> 8 ) <= 8190UL )
a = ( a * b + 0x8000UL ) >> 16;
else
@@ -614,12 +615,12 @@
/* XXX: this function does not allow 64-bit arguments */
- FT_MOVE_SIGN( a_, s );
- FT_MOVE_SIGN( b_, s );
-
a = (FT_UInt32)a_;
b = (FT_UInt32)b_;
+ FT_MOVE_SIGN( a_, a, s );
+ FT_MOVE_SIGN( b_, b, s );
+
if ( b == 0 )
{
/* check for division by 0 */
@@ -770,12 +771,12 @@
FT_Int sx = 1, sy = 1, shift;
- FT_MOVE_SIGN( x_, sx );
- FT_MOVE_SIGN( y_, sy );
-
x = (FT_UInt32)x_;
y = (FT_UInt32)y_;
+ FT_MOVE_SIGN( x_, x, sx );
+ FT_MOVE_SIGN( y_, y, sy );
+
/* trivial cases */
if ( x == 0 )
{