From dc2c84ca713d4025634294bd1bbd458894049b94 Mon Sep 17 00:00:00 2001 From: Anton Kovalev Date: Thu, 28 Jul 2016 17:45:29 +0300 Subject: [PATCH 1/2] [strategies] prevent integer overflow during segment touch ratio calculation --- .../strategies/cartesian/intersection.hpp | 63 ++++++++++++++----- 1 file changed, 48 insertions(+), 15 deletions(-) diff --git a/include/boost/geometry/strategies/cartesian/intersection.hpp b/include/boost/geometry/strategies/cartesian/intersection.hpp index 233bb50b64..430badac85 100644 --- a/include/boost/geometry/strategies/cartesian/intersection.hpp +++ b/include/boost/geometry/strategies/cartesian/intersection.hpp @@ -339,24 +339,57 @@ struct cartesian_segments // (only calculated for non-collinear segments) if (! collinear) { + math::detail::equals_factor_policy + policy(robust_dx_a, robust_dy_a, robust_dx_b, robust_dy_b); + + robust_coordinate_type const zero = 0; + robust_coordinate_type robust_da0, robust_da; robust_coordinate_type robust_db0, robust_db; - cramers_rule(robust_dx_a, robust_dy_a, robust_dx_b, robust_dy_b, - get<0>(robust_a1) - get<0>(robust_b1), - get<1>(robust_a1) - get<1>(robust_b1), - robust_da0, robust_da); + bool robust_da0_is_zero = false; + if (sides.get<0, 0>() == 0) + { + robust_da0 = 1; + robust_da = 0; + } + else if (sides.get<0, 1>() == 0) + { + robust_da0 = 1; + robust_da = 1; + } + else + { + cramers_rule(robust_dx_a, robust_dy_a, robust_dx_b, robust_dy_b, + get<0>(robust_a1) - get<0>(robust_b1), + get<1>(robust_a1) - get<1>(robust_b1), + robust_da0, robust_da); - cramers_rule(robust_dx_b, robust_dy_b, robust_dx_a, robust_dy_a, - get<0>(robust_b1) - get<0>(robust_a1), - get<1>(robust_b1) - get<1>(robust_a1), - robust_db0, robust_db); + robust_da0_is_zero = math::detail::equals_by_policy(robust_da0, zero, policy); + } - math::detail::equals_factor_policy - policy(robust_dx_a, robust_dy_a, robust_dx_b, robust_dy_b); - robust_coordinate_type const zero = 0; - if (math::detail::equals_by_policy(robust_da0, zero, policy) - || math::detail::equals_by_policy(robust_db0, zero, policy)) + bool robust_db0_is_zero = false; + if (sides.get<1, 0>() == 0) + { + robust_db0 = 1; + robust_db = 0; + } + else if (sides.get<1, 1>() == 0) + { + robust_db0 = 1; + robust_db = 1; + } + else + { + cramers_rule(robust_dx_b, robust_dy_b, robust_dx_a, robust_dy_a, + get<0>(robust_b1) - get<0>(robust_a1), + get<1>(robust_b1) - get<1>(robust_a1), + robust_db0, robust_db); + + robust_db0_is_zero = math::detail::equals_by_policy(robust_db0, zero, policy); + } + + if (robust_da0_is_zero || robust_db0_is_zero) { // If this is the case, no rescaling is done for FP precision. // We set it to collinear, but it indicates a robustness issue. @@ -536,7 +569,7 @@ struct cartesian_segments int const a2_wrt_b = position_value(oa_2, ob_1, ob_2); int const b1_wrt_a = position_value(ob_1, oa_1, oa_2); int const b2_wrt_a = position_value(ob_2, oa_1, oa_2); - + // fix the ratios if necessary // CONSIDER: fixing ratios also in other cases, if they're inconsistent // e.g. if ratio == 1 or 0 (so IP at the endpoint) @@ -553,7 +586,7 @@ struct cartesian_segments { ra_from.assign(1, 1); rb_to.assign(0, 1); - } + } if (a2_wrt_b == 1) { From 3f34a01e2e343b11a1020a081ad83744ae7134bc Mon Sep 17 00:00:00 2001 From: Anton Kovalev Date: Thu, 28 Jul 2016 17:45:48 +0300 Subject: [PATCH 2/2] [test] fix tests --- test/algorithms/is_simple.cpp | 5 +++-- test/algorithms/is_valid.cpp | 2 +- .../intersection/intersection_linear_linear.cpp | 6 +++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/test/algorithms/is_simple.cpp b/test/algorithms/is_simple.cpp index 41cef5ed56..c26c3fa120 100644 --- a/test/algorithms/is_simple.cpp +++ b/test/algorithms/is_simple.cpp @@ -268,11 +268,12 @@ BOOST_AUTO_TEST_CASE( test_geometry_with_NaN_coordinates ) bg::read_wkt("LINESTRING(-1 1,1.115235e+308 1.738137e+308)", ls2); // the intersection of the two linestrings is a new linestring - // (multilinestring with a single element) that has NaN coordinates + // (multilinestring with a single element) that is an isolated point multi_linestring_type mls; bg::intersection(ls1, ls2, mls); - test_simple(mls, true, false); + // "isolated point"-linestring is not simple + test_simple(mls, false, false); } BOOST_AUTO_TEST_CASE( test_is_simple_variant ) diff --git a/test/algorithms/is_valid.cpp b/test/algorithms/is_valid.cpp index b683b4c219..706dbece80 100644 --- a/test/algorithms/is_valid.cpp +++ b/test/algorithms/is_valid.cpp @@ -262,7 +262,7 @@ inline void test_open_rings() typedef bg::model::ring CG; // ccw, closed ring typedef bg::model::ring CW_OG; // cw, open ring typedef bg::model::ring CW_CG; // cw, closed ring - + typedef validity_tester_areal tester; typedef test_valid test; diff --git a/test/algorithms/set_operations/intersection/intersection_linear_linear.cpp b/test/algorithms/set_operations/intersection/intersection_linear_linear.cpp index 5224f10f4c..385c0d24a9 100644 --- a/test/algorithms/set_operations/intersection/intersection_linear_linear.cpp +++ b/test/algorithms/set_operations/intersection/intersection_linear_linear.cpp @@ -1309,7 +1309,7 @@ BOOST_AUTO_TEST_CASE( test_intersection_ml_ml_degenerate ) (8.5655 2.85228),(5.26567 4.81254),(4 3.8),\ (1.4995 3.27036),(0.591231 3.43401),\ (-0.706503 3.66784),\ - (-0.7654 8.88178e-16,-0.7654 0,5 3))"), + (-0.7654 0,5 3))"), from_wkt("MULTILINESTRING((1.87562 6.68515),(1.60494 6),\ (1.18124 4.9275),(1.00439 4.47984),(0.91526 4.25422),\ (0.729883 3.78498),(0.614728 3.49349),\ @@ -1340,7 +1340,7 @@ BOOST_AUTO_TEST_CASE( test_intersection_ml_ml_degenerate ) (9.98265 0.00543606),(9.09826 -100.515944),\ (7.08745 -329.0674155),(5.06428 -559.024344),\ (3.23365 -767.0972558),(3.16036 -775.427199),\ - (-0.7654 8.88178e-16,-0.7654 0,5 3))"), + (-0.7654 0,5 3))"), #endif "mlmli21", 1e-4 @@ -1355,7 +1355,7 @@ BOOST_AUTO_TEST_CASE( test_intersection_ml_ml_spikes ) { #ifdef BOOST_GEOMETRY_TEST_DEBUG std::cout << std::endl << std::endl << std::endl; - std::cout << "*** MULTILINESTRING / MULTILINESTRING INTERSECTION" + std::cout << "*** MULTILINESTRING / MULTILINESTRING INTERSECTION" << " (WITH SPIKES) ***" << std::endl; std::cout << std::endl;