diff --git a/src/user/user_mesh.cc b/src/user/user_mesh.cc
index 827f8174..5da757ba 100644
--- a/src/user/user_mesh.cc
+++ b/src/user/user_mesh.cc
@@ -1506,6 +1506,10 @@ void mjCMesh::MakeGraph(void) {
throw mjCError(this, "could not allocate data for qhull");
}
for (int i=0; i<3*nvert_; i++) {
+ if (!std::isfinite(vert_[i])) {
+ mju_free(data);
+ throw mjCError(this, "vertex coordinate %d is not finite", NULL, i);
+ }
data[i] = (double)vert_[i];
}
diff --git a/test/user/user_mesh_test.cc b/test/user/user_mesh_test.cc
index 497d25d0..a4bd0052 100644
--- a/test/user/user_mesh_test.cc
+++ b/test/user/user_mesh_test.cc
@@ -923,6 +923,28 @@ TEST_F(MjCMeshTest, MissingTexCoord) {
EXPECT_THAT(error.data(), HasSubstr("texcoord must be 2*nv"));
}
+// ----------------------------- qhull ----------------------------------------
+
+TEST_F(MjCMeshTest, NaNConvexHullDisallowed) {
+ static constexpr char xml[] = R"(
+
+
+
+
+
+ )";
+ static char warning[1024];
+ warning[0] = '\0';
+ mju_user_warning = [](const char* msg) {
+ util::strcpy_arr(warning, msg);
+ };
+ std::array error;
+ mjModel* model = LoadModelFromString(xml, error.data(), error.size());
+ EXPECT_THAT(model, testing::IsNull());
+ EXPECT_THAT(error.data(), HasSubstr("vertex coordinate 0 is not finite"));
+ mj_deleteModel(model);
+}
+
} // namespace
} // namespace mujoco