From 4a98497529eb6f5a07d334583962bdffd65dd380 Mon Sep 17 00:00:00 2001 From: sumeerbhola Date: Wed, 2 Sep 2020 09:45:45 -0400 Subject: [PATCH] Fix segfault in SimplePointInAreaLocator caused by casting MultiPolygon to Polygon References https://trac.osgeo.org/geos/ticket/1047 References https://github.com/cockroachdb/cockroach/issues/53254 --- .../locate/SimplePointInAreaLocator.cpp | 20 ++++++++++--------- tests/unit/algorithm/PointLocatorTest.cpp | 19 ++++++++++++++++++ 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/algorithm/locate/SimplePointInAreaLocator.cpp b/src/algorithm/locate/SimplePointInAreaLocator.cpp index 93e9482872..399bab308c 100644 --- a/src/algorithm/locate/SimplePointInAreaLocator.cpp +++ b/src/algorithm/locate/SimplePointInAreaLocator.cpp @@ -67,15 +67,17 @@ SimplePointInAreaLocator::locateInGeometry(const Coordinate& p, const Geometry* } if (geom->getNumGeometries() == 1) { - return locatePointInPolygon(p, dynamic_cast(geom->getGeometryN(0))); - } else { - for (size_t i = 0; i < geom->getNumGeometries(); i++) { - const Geometry* gi = geom->getGeometryN(i); - - auto loc = locateInGeometry(p, gi); - if(loc != Location::EXTERIOR) { - return loc; - } + auto poly = dynamic_cast(geom->getGeometryN(0)); + if (poly) { + return locatePointInPolygon(p, poly); + } + // Else it is a collection with a single element. Will be handled below. + } + for (size_t i = 0; i < geom->getNumGeometries(); i++) { + const Geometry* gi = geom->getGeometryN(i); + auto loc = locateInGeometry(p, gi); + if(loc != Location::EXTERIOR) { + return loc; } } diff --git a/tests/unit/algorithm/PointLocatorTest.cpp b/tests/unit/algorithm/PointLocatorTest.cpp index bc63b0776d..a230d96864 100644 --- a/tests/unit/algorithm/PointLocatorTest.cpp +++ b/tests/unit/algorithm/PointLocatorTest.cpp @@ -5,6 +5,7 @@ #include // geos #include +#include #include #include #include @@ -56,6 +57,14 @@ runPtLocator(Location expected, const Coordinate& pt, ensure_equals(loc, expected); } +void +runSimplePtLocator(Location expected, const Coordinate& pt, + const std::string& wkt) +{ + GeomPtr geom(reader.read(wkt)); + Location loc = geos::algorithm::locate::SimplePointInAreaLocator::locate(pt, geom.get()); + ensure_equals(loc, expected); +} // // Test Cases @@ -111,5 +120,15 @@ void object::test<5> "MULTIPOINT ((1 1), (0 0))"); } +// 6 - TestPointLocator Point inside GeometryCollection containing MultiPolygon, using SimplePointInAreaLocator. +template<> +template<> +void object::test<6> +() +{ + runSimplePtLocator(Location::INTERIOR, Coordinate(0, 0), + "GEOMETRYCOLLECTION (MULTIPOLYGON (((-1 -1, 1 -1, 1 1, -1 1, -1 -1))))"); +} + } // namespace tut