[dia] Bug 710818 - Overflow safe wrappers for acos/asin



commit 846a7ff5b5cb5d21f3c97d21f7a1890a0fcfb65b
Author: Hans Breuer <hans breuer org>
Date:   Sun Nov 17 11:29:42 2013 +0100

    Bug 710818 - Overflow safe wrappers for acos/asin
    
    acos() and asin() are only defined in a certain range. Implement some
    range/overflow safe wrappers rather than potentially passing infinite
    to other modules (e.g. cairo did assert() on it.)

 lib/arrows.c         |    4 ++--
 lib/boundingbox.c    |    2 +-
 lib/geometry.c       |   40 ++++++++++++++++++++++++++++++++++++++--
 lib/geometry.h       |    3 +++
 lib/libdia.def       |    3 +++
 plug-ins/hpgl/hpgl.c |    6 +++---
 6 files changed, 50 insertions(+), 8 deletions(-)
---
diff --git a/lib/arrows.c b/lib/arrows.c
index 043afee..8de39fe 100644
--- a/lib/arrows.c
+++ b/lib/arrows.c
@@ -1613,7 +1613,7 @@ draw_rounded(DiaRenderer *renderer, Point *to, Point *from,
     p.x += delta.x * rapport;
     p.y += delta.y * rapport;
   }  
-  angle_start = 90.0 - asin((p.y - to->y) / rayon) * (180.0 / 3.14);
+  angle_start = 90.0 - dia_asin((p.y - to->y) / rayon) * (180.0 / 3.14);
   if (p.x - to->x < 0) { angle_start = 360.0 - angle_start;  }
   
   DIA_RENDERER_GET_CLASS(renderer)->draw_arc(renderer, &p, width, length, angle_start, angle_start - 180.0, 
fg_color);
@@ -1665,7 +1665,7 @@ draw_open_rounded(DiaRenderer *renderer, Point *to, Point *from,
     p.x += delta.x * rapport;
     p.y += delta.y * rapport;
   }  
-  angle_start = 90.0 - asin((p.y - to->y) / rayon) * (180.0 / 3.14);
+  angle_start = 90.0 - dia_asin((p.y - to->y) / rayon) * (180.0 / 3.14);
   if (p.x - to->x < 0) { angle_start = 360.0 - angle_start;  }
 
   p_line = p;
diff --git a/lib/boundingbox.c b/lib/boundingbox.c
index eb71f35..4c14892 100644
--- a/lib/boundingbox.c
+++ b/lib/boundingbox.c
@@ -502,7 +502,7 @@ polybezier_bbox(const BezPoint *pts, int numpoints,
       else if (co <= -1.0)
         alpha = M_PI;
       else
-        alpha = acos(-co); 
+        alpha = dia_acos(-co);
       if (co > -0.9816) { /* 0.9816 = cos(11deg) */
         /* we have a pointy join. */
         real overshoot;
diff --git a/lib/geometry.c b/lib/geometry.c
index d42b785..a67427a 100644
--- a/lib/geometry.c
+++ b/lib/geometry.c
@@ -474,7 +474,7 @@ real dot2(Point *p1, Point *p2)
   if ( d != 0.0 )
   {
     t = (p1->x*p2->x+p1->y*p2->y)/d;
-    return (acos(t));
+    return (dia_acos(t));
   }
   else
   {
@@ -818,4 +818,40 @@ dia_matrix_is_invertible (const DiaMatrix *matrix)
   det = a*d - b*c;
 
   return finite(det) && det != 0.0;
-}
\ No newline at end of file
+}
+
+/*!
+ * \brief asin wrapped to limit to valid result range
+ *
+ * Although clipping the value might hide some miscalculation
+ * elsewhere this should still be used in all of Dia. Continuing
+ * calculation with bogus values might final fall on our foots
+ * because rendering libraries might not be graceful.
+ * See https://bugzilla.gnome.org/show_bug.cgi?id=710818
+ */
+real
+dia_asin (real x)
+{
+  real r = asin (x);
+  /* clamp to valid range */
+  if (r < -M_PI/2)
+    return -M_PI/2;
+  else if (r > M_PI/2)
+    return M_PI/2;
+  return r;
+}
+
+/*!
+ * \brief acos wrapped to limit to valid result range
+ */
+real
+dia_acos (real x)
+{
+  real r = acos (x);
+  /* clamp to valid range */
+  if (r < 0)
+    return 0;
+  else if (r > M_PI)
+    return M_PI;
+  return r;
+}
diff --git a/lib/geometry.h b/lib/geometry.h
index 920f1ac..8229a08 100644
--- a/lib/geometry.h
+++ b/lib/geometry.h
@@ -381,6 +381,9 @@ int  three_point_circle(const Point *p1, const Point *p2, const Point *p3,
 real point_cross(Point *p1, Point *p2);
 Point calculate_object_edge(Point *objmid, Point *end, DiaObject *obj);
 
+real dia_asin (real x);
+real dia_acos (real x);
+
 G_END_DECLS
 
 #endif /* GEOMETRY_H */
diff --git a/lib/libdia.def b/lib/libdia.def
index 24331dd..a573ce4 100644
--- a/lib/libdia.def
+++ b/lib/libdia.def
@@ -188,6 +188,9 @@ EXPORTS
 
  destroy_object_list
 
+ dia_asin
+ dia_acos
+
  dia_alignment_selector_get_alignment
  dia_alignment_selector_new
  dia_alignment_selector_set_alignment
diff --git a/plug-ins/hpgl/hpgl.c b/plug-ins/hpgl/hpgl.c
index 43e2ccf..dbb16ad 100644
--- a/plug-ins/hpgl/hpgl.c
+++ b/plug-ins/hpgl/hpgl.c
@@ -478,7 +478,7 @@ draw_ellipse_by_arc (DiaRenderer *renderer,
   b = height / 2;
   e = sqrt(a*a - b*b);
 
-  alpha = 0.25*M_PI - asin((e/a) * sin(0.75*M_PI));
+  alpha = 0.25*M_PI - dia_asin((e/a) * sin(0.75*M_PI));
   d = 2*a*sin(alpha);
 
   c = (sin(0.25*M_PI) * (2*e + d)) / sin(0.75*M_PI - alpha);
@@ -488,7 +488,7 @@ draw_ellipse_by_arc (DiaRenderer *renderer,
 
   /* draw arcs */
   g = sqrt((a-x)*(a-x) + y*y);
-  gamma = acos((a-x)/g);
+  gamma = dia_acos((a-x)/g);
   r = (sin(gamma) * g) / sin(M_PI-2*gamma);
 
   pt.y = center->y;
@@ -500,7 +500,7 @@ draw_ellipse_by_arc (DiaRenderer *renderer,
 
 
   g = sqrt((b-y)*(b-y) + x*x);
-  gamma = acos((b-y)/g);
+  gamma = dia_acos((b-y)/g);
   r = (sin(gamma) * g) / sin(M_PI-2*gamma);
 
   pt.x = center->x;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]