mapbox / earcut

The fastest and smallest JavaScript polygon triangulation library for your WebGL apps
ISC License
2.21k stars 207 forks source link

Infinite loop with holes due to inconsistent linked list state #135

Closed eile closed 3 years ago

eile commented 4 years ago

Hi,

We've hit a fairly uncommon bug when tesselating a large polygons with holes. I haven't fully figured it out, but the incoming linked list is inconsistent. See below for the workaround we applied.

For my own sanity, I ported it to typescript to understand and work on it. If you are interested in switching to TS, I can provide the typescript file.


     if (p.z === null) {
       p.z = zOrder(p.x, p.y, minX, minY, invSize);
     }
+
+    // Detect inconsistent state: Somehow this happens when holes are present. Fixup linked list and try again
+    if (p.prev.next !== p || p.next.prev !== p) {
+      p.prev.next = p;
+      p.next.prev = p;
+      return indexCurve(start, minX, minY, invSize);
+    }
     p.prevZ = p.prev;
     p.nextZ = p.next;
   }```
mrgreywater commented 4 years ago

Thank you for your information. In place of the workaround, could you add an assertion and dump the polygon to reproduce the issue, please?

eile commented 4 years ago

Might be a dup of #127 (we are colleagues). Will dump the poly in a bit.

mourner commented 4 years ago

Thanks a lot for the report! We're not planning on switching to TS, but very interested in any insights that could help fix the issue. Inconsistent prev/next state is a good clue — if it does fix the issue, we could try adding a bunch of asserts throughout the code to see the exact point where it becomes corrupted, and fix the root cause.

eile commented 4 years ago

Here is the call in question 135.log

eile commented 4 years ago

@mrgreywater @mourner Could you reproduce the problem? Do you have an idea on when you'll be able to fix this?

mourner commented 3 years ago

This may no longer be reproducible according to #148 — let's close and reopen if there's a test case that still breaks.