diff --git a/src/draco/compression/mesh/mesh_sequential_decoder.cc b/src/draco/compression/mesh/mesh_sequential_decoder.cc index 124df3345..790e3ceb9 100644 --- a/src/draco/compression/mesh/mesh_sequential_decoder.cc +++ b/src/draco/compression/mesh/mesh_sequential_decoder.cc @@ -65,7 +65,7 @@ bool MeshSequentialDecoder::DecodeConnectivity() { return false; } if (connectivity_method == 0) { - if (!DecodeAndDecompressIndices(num_faces)) { + if (!DecodeAndDecompressIndices(num_faces, num_points)) { return false; } } else { @@ -78,6 +78,9 @@ bool MeshSequentialDecoder::DecodeConnectivity() { if (!buffer()->Decode(&val)) { return false; } + if (val >= num_points) { + return false; + } face[j] = val; } mesh()->AddFace(face); @@ -91,6 +94,9 @@ bool MeshSequentialDecoder::DecodeConnectivity() { if (!buffer()->Decode(&val)) { return false; } + if (val >= num_points) { + return false; + } face[j] = val; } mesh()->AddFace(face); @@ -105,6 +111,9 @@ bool MeshSequentialDecoder::DecodeConnectivity() { if (!DecodeVarint(&val, buffer())) { return false; } + if (val >= num_points) { + return false; + } face[j] = val; } mesh()->AddFace(face); @@ -118,6 +127,9 @@ bool MeshSequentialDecoder::DecodeConnectivity() { if (!buffer()->Decode(&val)) { return false; } + if (val >= num_points) { + return false; + } face[j] = val; } mesh()->AddFace(face); @@ -138,7 +150,8 @@ bool MeshSequentialDecoder::CreateAttributesDecoder(int32_t att_decoder_id) { new LinearSequencer(point_cloud()->num_points()))))); } -bool MeshSequentialDecoder::DecodeAndDecompressIndices(uint32_t num_faces) { +bool MeshSequentialDecoder::DecodeAndDecompressIndices(uint32_t num_faces, + uint32_t num_points) { // Get decoded indices differences that were encoded with an entropy code. std::vector indices_buffer(num_faces * 3); if (!DecodeSymbols(num_faces * 3, 1, buffer(), indices_buffer.data())) { @@ -167,6 +180,10 @@ bool MeshSequentialDecoder::DecodeAndDecompressIndices(uint32_t num_faces) { } } const int32_t index_value = index_diff + last_index_value; + if (index_value < 0 || + static_cast(index_value) >= num_points) { + return false; + } face[j] = index_value; last_index_value = index_value; } diff --git a/src/draco/compression/mesh/mesh_sequential_decoder.h b/src/draco/compression/mesh/mesh_sequential_decoder.h index 3a86c75d5..7c3acdc50 100644 --- a/src/draco/compression/mesh/mesh_sequential_decoder.h +++ b/src/draco/compression/mesh/mesh_sequential_decoder.h @@ -30,8 +30,9 @@ class MeshSequentialDecoder : public MeshDecoder { private: // Decodes face indices that were compressed with an entropy code. + // |num_points| is used to validate that every decoded index is in range. // Returns false on error. - bool DecodeAndDecompressIndices(uint32_t num_faces); + bool DecodeAndDecompressIndices(uint32_t num_faces, uint32_t num_points); }; } // namespace draco