From f4d5ec9981e95fb1b50d130988c9c3b54c32e78d Mon Sep 17 00:00:00 2001 From: Matthew Fedderly Date: Thu, 5 Oct 2023 10:46:58 -0400 Subject: [PATCH] @turf/unkink-polygon - Fix a potentially unbounded array.push.apply --- CHANGELOG.md | 1 + .../turf-unkink-polygon/lib/simplepolygon.js | 4 +++- packages/turf-unkink-polygon/test.js | 22 +++++++++++++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index de699af641..01576deb8b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,7 @@ We intend to keep making breaking changes before 7.0.0 is fully released. If you - [`@turf/points-within-polygon`](points-within-polygon) Fix dropped properties on MultiPoint results (#2227) - [`@turf/random`](random) Throws error on invalid bbox inputs (#2172) - [`@turf/boolean-parallel`](boolean-parallel) Lines with 180 degree angle between them are also considered parallel (#2475) +- [`@turf/unkink-polygon`](unkink-polygon) Fix a maximum call stack size exceeded error with very large polygons (#2504) ## 📖 Documentation - [`@turf/bbox`][bbox] Improve documentation (#2153) diff --git a/packages/turf-unkink-polygon/lib/simplepolygon.js b/packages/turf-unkink-polygon/lib/simplepolygon.js index 17b9f26ed1..1036d93666 100644 --- a/packages/turf-unkink-polygon/lib/simplepolygon.js +++ b/packages/turf-unkink-polygon/lib/simplepolygon.js @@ -44,7 +44,9 @@ export default function (feature) { if (!equalArrays(ring[0], ring[ring.length - 1])) { ring.push(ring[0]); // Close input ring if it is not } - vertices.push.apply(vertices, ring.slice(0, ring.length - 1)); + for (var j = 0; j < ring.length - 1; j++) { + vertices.push(ring[j]); + } } if (!isUnique(vertices)) throw new Error( diff --git a/packages/turf-unkink-polygon/test.js b/packages/turf-unkink-polygon/test.js index f0ec7f3811..22d87dc584 100644 --- a/packages/turf-unkink-polygon/test.js +++ b/packages/turf-unkink-polygon/test.js @@ -36,6 +36,28 @@ test("unkink-polygon", (t) => { t.end(); }); +test("issue #2504", (t) => { + // fill coords with a circle with an arbitrary number of points + const coords = []; + const points = 1000000; + for (let i = 0; i < points; i++) { + const theta = (i / points) * (2 * Math.PI); + coords.push([Math.sin(theta), Math.cos(theta)]); + } + coords.push(coords[0]); + + try { + unkinkPolygon({ type: "Polygon", coordinates: [coords] }); + t.pass( + "large number of coordinates in a single ring should not cause an error" + ); + } catch (e) { + t.fail(e); + } + + t.end(); +}); + test("unkink-polygon -- throws", (t) => { var array = [1, 2, 3, 4, 5]; for (const value in array) {