From 3771078c02bb478554cd4a6e93272ca4a4edf0e4 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 ++++ modules/gltf/gltf_document.cpp | 14 ++++++++++++++ 4 files changed, 33 insertions(+) diff --git a/core/math/geometry.cpp b/core/math/geometry.cpp index 7568b1d56ed3..b86d44c4e28c 100644 --- a/core/math/geometry.cpp +++ b/core/math/geometry.cpp @@ -1549,3 +1549,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 de844ba2badb..c530e93f55c9 100644 --- a/core/math/geometry.h +++ b/core/math/geometry.h @@ -1020,6 +1020,7 @@ class Geometry { 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); private: static Vector> _polypaths_do_operation(PolyBooleanOperation p_op, const Vector &p_polypath_a, const Vector &p_polypath_b, bool is_a_open = false); diff --git a/core/math/vertex_cache_optimizer.cpp b/core/math/vertex_cache_optimizer.cpp index bb0e9090abbe..7b2695fa6705 100644 --- a/core/math/vertex_cache_optimizer.cpp +++ b/core/math/vertex_cache_optimizer.cpp @@ -30,6 +30,7 @@ #include "vertex_cache_optimizer.h" +#include "core/math/geometry.h" #include "core/math/math_funcs.h" // Precalculate the tables. @@ -287,6 +288,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/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index f48ea0b19083..b5d454c43255 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -2936,6 +2936,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); }