From 08f4960b231cde0223854ad29d2a9658dc7266dc Mon Sep 17 00:00:00 2001 From: lawnjelly Date: Wed, 31 Jul 2024 10:14:34 +0100 Subject: [PATCH] Verify GLTF indices to prevent crash with corrupt files Also verify prior to vertex optimization. --- core/math/geometry.cpp | 14 ++++++++++++++ core/math/geometry.h | 1 + core/math/vertex_cache_optimizer.cpp | 4 ++++ editor_modules/gltf/gltf_document.cpp | 14 ++++++++++++++ 4 files changed, 33 insertions(+) diff --git a/core/math/geometry.cpp b/core/math/geometry.cpp index f08ad0142..06487b4ce 100644 --- a/core/math/geometry.cpp +++ b/core/math/geometry.cpp @@ -1860,3 +1860,17 @@ void Geometry::sort_polygon_winding(Vector &r_verts, bool p_clockwise) r_verts.invert(); } } + +bool Geometry::verify_indices(const int *p_indices, int p_num_indices, int p_num_vertices) { + ERR_FAIL_NULL_V(p_indices, false); + ERR_FAIL_COND_V(p_num_indices < 0, false); + ERR_FAIL_COND_V(p_num_vertices < 0, false); + + for (int n = 0; n < p_num_indices; n++) { + if ((unsigned int)p_indices[n] >= (unsigned int)p_num_vertices) { + return false; + } + } + + return true; +} diff --git a/core/math/geometry.h b/core/math/geometry.h index 284d07647..cb88ea1a0 100644 --- a/core/math/geometry.h +++ b/core/math/geometry.h @@ -1057,6 +1057,7 @@ public: static Vector compute_convex_mesh_points(const Plane *p_planes, int p_plane_count, real_t p_epsilon = CMP_EPSILON); static bool convex_hull_intersects_convex_hull(const Plane *p_planes_a, int p_plane_count_a, const Plane *p_planes_b, int p_plane_count_b); static real_t calculate_convex_hull_volume(const Geometry::MeshData &p_md); + static bool verify_indices(const int *p_indices, int p_num_indices, int p_num_vertices); static _FORCE_INLINE_ Vector bresenham_line(int x0, int x1, int y0, int y1) { Vector points; diff --git a/core/math/vertex_cache_optimizer.cpp b/core/math/vertex_cache_optimizer.cpp index 1207aedd4..d8112053f 100644 --- a/core/math/vertex_cache_optimizer.cpp +++ b/core/math/vertex_cache_optimizer.cpp @@ -31,6 +31,7 @@ #include "vertex_cache_optimizer.h" +#include "core/math/geometry.h" #include "core/math/math_funcs.h" // Precalculate the tables. @@ -288,6 +289,9 @@ bool VertexCacheOptimizer::reorder_indices_pool(PoolVector &r_indices, uint } bool VertexCacheOptimizer::reorder_indices(LocalVector &r_indices, uint32_t p_num_triangles, uint32_t p_num_verts) { + // If the mesh contains invalid indices, abort. + ERR_FAIL_COND_V(!Geometry::verify_indices(r_indices.ptr(), r_indices.size(), p_num_verts), false); + LocalVector temp; temp.resize(r_indices.size()); if (_reorder_indices((VERTEX_INDEX_TYPE *)temp.ptr(), (VERTEX_INDEX_TYPE *)r_indices.ptr(), p_num_triangles, p_num_verts)) { diff --git a/editor_modules/gltf/gltf_document.cpp b/editor_modules/gltf/gltf_document.cpp index 3e868f4f2..a7af37d07 100644 --- a/editor_modules/gltf/gltf_document.cpp +++ b/editor_modules/gltf/gltf_document.cpp @@ -2959,6 +2959,20 @@ Error GLTFDocument::_parse_meshes(Ref p_state) { mat = mat3d; } int32_t mat_idx = import_mesh->get_surface_count(); + + // Check for invalid indices. + if (array[Mesh::ARRAY_INDEX] && array[Mesh::ARRAY_INDEX] != Variant()) { + const Vector &inds = array[Mesh::ARRAY_INDEX]; + + if (array[Mesh::ARRAY_VERTEX] && array[Mesh::ARRAY_VERTEX] != Variant()) { + const Vector &vertices = array[Mesh::ARRAY_VERTEX]; + int num_verts = vertices.size(); + + // The mesh contains invalid indices, abort. + ERR_FAIL_COND_V(!Geometry::verify_indices(inds.ptr(), inds.size(), num_verts), ERR_FILE_CORRUPT); + } + } + import_mesh->add_surface_from_arrays(primitive, array, morphs, p_state->compress_flags); import_mesh->surface_set_material(mat_idx, mat); }