From 4b21ab34c07f90d8d0e6ffeb19b59a5042032875 Mon Sep 17 00:00:00 2001 From: Lazizbek Ergashev Date: Fri, 4 Sep 2026 14:19:54 +0500 Subject: [PATCH] ptcloud: bounds-check split() results in PLY header parsing --- modules/ptcloud/src/io_ply.cpp | 15 ++++++-- modules/ptcloud/test/test_pointcloud_io.cpp | 40 +++++++++++++++++++++ 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/modules/ptcloud/src/io_ply.cpp b/modules/ptcloud/src/io_ply.cpp index 9652bda8aa..5d9b025e46 100644 --- a/modules/ptcloud/src/io_ply.cpp +++ b/modules/ptcloud/src/io_ply.cpp @@ -50,11 +50,16 @@ bool PlyDecoder::parseHeader(std::ifstream &file, int& nTexCoords) { e = trimSpaces(e); } - if (splitArr[0] != "format") + if (splitArr.empty() || splitArr[0] != "format") { CV_LOG_ERROR(NULL, "Provided file doesn't have format"); return false; } + if (splitArr.size() < 2) + { + CV_LOG_ERROR(NULL, "Provided PLY file format is not supported"); + return false; + } if (splitArr[1] == "ascii") { m_inputDataFormat = DataFormat::ASCII; @@ -104,7 +109,13 @@ bool PlyDecoder::parseHeader(std::ifstream &file, int& nTexCoords) { e = trimSpaces(e); } - std::string elemName = splitArrElem.at(1); + if (splitArrElem.size() < 2) + { + CV_LOG_ERROR(NULL, "Element description has " << splitArrElem.size() + << " words instead of at least 2"); + return false; + } + std::string elemName = splitArrElem[1]; if (elemName == "vertex") { elemRead = READ_VERTEX; diff --git a/modules/ptcloud/test/test_pointcloud_io.cpp b/modules/ptcloud/test/test_pointcloud_io.cpp index e18c54d66e..4dbf2e3eb2 100644 --- a/modules/ptcloud/test/test_pointcloud_io.cpp +++ b/modules/ptcloud/test/test_pointcloud_io.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "test_precomp.hpp" #include "opencv2/ts.hpp" @@ -296,4 +297,43 @@ TEST(PointCloud, SaveBadExtension) cv::savePointCloud(folder + "pointcloudio/fake.fake", points, normals); } +TEST(PointCloud, LoadPlyEmptyFormatLine) +{ + std::string path = tempfile("empty_format.ply"); + std::ofstream file(path, std::ios::binary); + file << "ply\n\n"; + file.close(); + + std::vector points, normals, rgb; + cv::loadPointCloud(path, points, normals, rgb); + EXPECT_TRUE(points.empty()); + std::remove(path.c_str()); +} + +TEST(PointCloud, LoadPlyFormatLineNoSeparator) +{ + std::string path = tempfile("no_separator_format.ply"); + std::ofstream file(path, std::ios::binary); + file << "ply\nformat\r\r\r\r\r\r\r\r\r\r\r\r\n"; + file.close(); + + std::vector points, normals, rgb; + cv::loadPointCloud(path, points, normals, rgb); + EXPECT_TRUE(points.empty()); + std::remove(path.c_str()); +} + +TEST(PointCloud, LoadPlyMalformedElementLine) +{ + std::string path = tempfile("malformed_element.ply"); + std::ofstream file(path, std::ios::binary); + file << "ply\nformat ascii 1.0\nelement\nend_header\n"; + file.close(); + + std::vector points, normals, rgb; + cv::loadPointCloud(path, points, normals, rgb); + EXPECT_TRUE(points.empty()); + std::remove(path.c_str()); +} + }} /* namespace opencv_test */