diff --git a/extern/glow-extras b/extern/glow-extras
index cabc984b6ed98c971263fd305a10a37f53b88d05..366c039647be09094da3226940aa189c5a2de8ea 160000
--- a/extern/glow-extras
+++ b/extern/glow-extras
@@ -1 +1 @@
-Subproject commit cabc984b6ed98c971263fd305a10a37f53b88d05
+Subproject commit 366c039647be09094da3226940aa189c5a2de8ea
diff --git a/extern/polymesh b/extern/polymesh
index 5719ed1860a475ddfcf3d7119027e4bd7910b0a9..b7ee88d6a832faccbd38a1b568c0467644111e2d 160000
--- a/extern/polymesh
+++ b/extern/polymesh
@@ -1 +1 @@
-Subproject commit 5719ed1860a475ddfcf3d7119027e4bd7910b0a9
+Subproject commit b7ee88d6a832faccbd38a1b568c0467644111e2d
diff --git a/extern/typed-geometry b/extern/typed-geometry
index f8a5e56373e3da67e7ea543424d0704950cbdfc1..e208eb529271780a1a77af4bc87631e10b800662 160000
--- a/extern/typed-geometry
+++ b/extern/typed-geometry
@@ -1 +1 @@
-Subproject commit f8a5e56373e3da67e7ea543424d0704950cbdfc1
+Subproject commit e208eb529271780a1a77af4bc87631e10b800662
diff --git a/tests/complex/triangulate-crash.cc b/tests/complex/triangulate-crash.cc
new file mode 100644
index 0000000000000000000000000000000000000000..7ce2ff480f5120342ecc843e0af098c440652eba
--- /dev/null
+++ b/tests/complex/triangulate-crash.cc
@@ -0,0 +1,116 @@
+#include <doctest.hh>
+
+#include <polymesh/Mesh.hh>
+#include <polymesh/algorithms/triangulate.hh>
+
+#include <glow-extras/viewer/canvas.hh>
+
+TEST_CASE("triangulate_naive crash")
+{
+    auto m = pm::Mesh();
+
+    std::vector<pm::vertex_index> vertices;
+    for (int i = 0; i < 26; ++i)
+        vertices.push_back(m.vertices().add());
+
+    std::vector<pm::vertex_index> vs;
+    vs.push_back(vertices[1]);
+    vs.push_back(vertices[2]);
+    vs.push_back(vertices[3]);
+    vs.push_back(vertices[4]);
+    vs.push_back(vertices[0]);
+    // std::reverse(vs.begin(), vs.end());
+    m.faces().add(vs);
+
+    vs.clear();
+    vs.push_back(vertices[12]);
+    vs.push_back(vertices[13]);
+    vs.push_back(vertices[9]);
+    // std::reverse(vs.begin(), vs.end());
+    m.faces().add(vs);
+
+    vs.clear();
+    vs.push_back(vertices[4]);
+    vs.push_back(vertices[3]);
+    vs.push_back(vertices[22]);
+    vs.push_back(vertices[18]);
+    // std::reverse(vs.begin(), vs.end());
+    m.faces().add(vs);
+
+    vs.clear();
+    vs.push_back(vertices[0]);
+    vs.push_back(vertices[4]);
+    vs.push_back(vertices[23]);
+    // std::reverse(vs.begin(), vs.end());
+    m.faces().add(vs);
+
+    vs.clear();
+    vs.push_back(vertices[18]);
+    vs.push_back(vertices[22]);
+    vs.push_back(vertices[25]);
+    // std::reverse(vs.begin(), vs.end());
+    m.faces().add(vs);
+
+    vs.clear();
+    vs.push_back(vertices[25]);
+    vs.push_back(vertices[22]);
+    vs.push_back(vertices[3]);
+    vs.push_back(vertices[2]);
+    vs.push_back(vertices[1]);
+    vs.push_back(vertices[13]);
+    vs.push_back(vertices[12]);
+    // std::reverse(vs.begin(), vs.end());
+    m.faces().add(vs);
+
+    vs.clear();
+    vs.push_back(vertices[13]);
+    vs.push_back(vertices[1]);
+    vs.push_back(vertices[0]);
+    vs.push_back(vertices[23]);
+    // std::reverse(vs.begin(), vs.end());
+    m.faces().add(vs);
+
+    vs.clear();
+    vs.push_back(vertices[9]);
+    vs.push_back(vertices[25]);
+    vs.push_back(vertices[12]);
+    // std::reverse(vs.begin(), vs.end());
+    m.faces().add(vs);
+
+    m.assert_consistency();
+    pm::triangulate_naive(m);
+
+    /*auto pos = m.vertices().make_attribute<tg::pos3>();
+    tg::rng rng;
+    for (auto v : m.vertices())
+        pos[v] = uniform(rng, boundary_of(tg::sphere3::unit));
+    for (auto i = 0; i < 20; ++i)
+    {
+        auto new_pos = pos;
+        for (auto v : m.vertices())
+        {
+            if (v.is_isolated())
+                continue;
+
+            auto np = v.adjacent_vertices().avg(pos);
+            new_pos[v] = tg::mix(pos[v], np, 0.2f);
+        }
+        for (auto& p : new_pos)
+            p = tg::pos3(normalize(tg::vec3(p)));
+        pos = new_pos;
+    }
+
+    auto c = gv::canvas();
+    for (auto v : m.vertices())
+        if (!v.is_isolated())
+            c.add_point(pos[v]).label(std::to_string(int(v)));
+    for (auto e : m.edges())
+    {
+        auto p0 = pos[e.vertexA()];
+        auto p1 = pos[e.vertexB()];
+        if (e.is_boundary())
+            c.add_line(p0, p1, tg::color3::red);
+        else
+            c.add_line(p0, p1);
+    }*/
+}