diff --git a/io/src/obj_io.cpp b/io/src/obj_io.cpp index 095b81e483d..6116e66c36e 100644 --- a/io/src/obj_io.cpp +++ b/io/src/obj_io.cpp @@ -37,6 +37,7 @@ */ #include #include +#include #include #include #include @@ -654,6 +655,12 @@ pcl::OBJReader::read (const std::string &file_name, pcl::PCLPointCloud2 &cloud, int v = std::stoi(f_st[0]); v = (v < 0) ? point_idx + v : v - 1; + if (v < 0 || static_cast (v) >= cloud.width) + { + PCL_ERROR ("[pcl::OBJReader::read] Vertex index out of bounds in line %s\n", line.c_str ()); + fs.close (); + return (-1); + } face_vertices.vertices[i - 1] = v; //handle normals @@ -661,7 +668,12 @@ pcl::OBJReader::read (const std::string &file_name, pcl::PCLPointCloud2 &cloud, { int n = std::stoi(n_st); n = (n < 0) ? normal_idx + n : n - 1; - + if (normal_mapping.empty() || n < 0 || static_cast (n) >= normals.size()) + { + PCL_ERROR ("[pcl::OBJReader::read] Normal index out of bounds in line %s\n", line.c_str ()); + fs.close (); + return (-1); + } normal_mapping[v] += normals[n]; normal_mapping_used = true; } @@ -676,6 +688,12 @@ pcl::OBJReader::read (const std::string &file_name, pcl::PCLPointCloud2 &cloud, fs.close (); return (-1); } + catch (const std::exception &exception) + { + PCL_ERROR ("[pcl::OBJReader::read] %s\n", exception.what ()); + fs.close (); + return (-1); + } if (normal_mapping_used && !normal_mapping.empty()) { @@ -899,6 +917,12 @@ pcl::OBJReader::read (const std::string &file_name, pcl::TextureMesh &mesh, int v = std::stoi(f_st[0]); v = (v < 0) ? v_idx + v : v - 1; + if (v < 0 || static_cast (v) >= mesh.cloud.width) + { + PCL_ERROR ("[pcl::OBJReader::read] Vertex index out of bounds in line %s\n", line.c_str ()); + fs.close (); + return (-1); + } face_vertices.vertices[i - 1] = v; //handle normals @@ -906,7 +930,12 @@ pcl::OBJReader::read (const std::string &file_name, pcl::TextureMesh &mesh, { int n = std::stoi(n_st); n = (n < 0) ? vn_idx + n : n - 1; - + if (normal_mapping.empty() || n < 0 || static_cast (n) >= normals.size()) + { + PCL_ERROR ("[pcl::OBJReader::read] Normal index out of bounds in line %s\n", line.c_str ()); + fs.close (); + return (-1); + } normal_mapping[v] += normals[n]; } @@ -914,7 +943,12 @@ pcl::OBJReader::read (const std::string &file_name, pcl::TextureMesh &mesh, { int vt = std::stoi(vt_st); vt = (vt < 0) ? vt_idx + vt : vt - 1; - + if (vt < 0 || static_cast (vt) >= vt_idx) + { + PCL_ERROR ("[pcl::OBJReader::read] Texture coordinate index out of bounds in line %s\n", line.c_str ()); + fs.close (); + return (-1); + } tex_indices.vertices.push_back(vt); } } @@ -931,6 +965,12 @@ pcl::OBJReader::read (const std::string &file_name, pcl::TextureMesh &mesh, fs.close (); return (-1); } + catch (const std::exception &exception) + { + PCL_ERROR ("[pcl::OBJReader::read] %s\n", exception.what ()); + fs.close (); + return (-1); + } if (!normal_mapping.empty()) { @@ -1097,6 +1137,12 @@ pcl::OBJReader::read (const std::string &file_name, pcl::PolygonMesh &mesh, int v = std::stoi(f_st[0]); v = (v < 0) ? v_idx + v : v - 1; + if (v < 0 || static_cast (v) >= mesh.cloud.width) + { + PCL_ERROR ("[pcl::OBJReader::read] Vertex index out of bounds in line %s\n", line.c_str ()); + fs.close (); + return (-1); + } face_vertices.vertices[i - 1] = v; //handle normals @@ -1104,7 +1150,12 @@ pcl::OBJReader::read (const std::string &file_name, pcl::PolygonMesh &mesh, { int n = std::stoi(n_st); n = (n < 0) ? vn_idx + n : n - 1; - + if (normal_mapping.empty() || n < 0 || static_cast (n) >= normals.size()) + { + PCL_ERROR ("[pcl::OBJReader::read] Normal index out of bounds in line %s\n", line.c_str ()); + fs.close (); + return (-1); + } normal_mapping[v] += normals[n]; normal_mapping_used = true; } @@ -1120,6 +1171,12 @@ pcl::OBJReader::read (const std::string &file_name, pcl::PolygonMesh &mesh, fs.close (); return (-1); } + catch (const std::exception &exception) + { + PCL_ERROR ("[pcl::OBJReader::read] %s\n", exception.what ()); + fs.close (); + return (-1); + } if (normal_mapping_used && !normal_mapping.empty()) { diff --git a/test/io/test_io.cpp b/test/io/test_io.cpp index 65676705191..f2e1c92086a 100644 --- a/test/io/test_io.cpp +++ b/test/io/test_io.cpp @@ -48,6 +48,7 @@ #include #include #include +#include #include #include // for setprecision #include @@ -1170,6 +1171,83 @@ TEST(PCL, loadOBJWithoutFaces) remove ("test_obj.obj"); } +TEST(PCL, OBJReadMalformedFaceIndices) +{ + const std::string fname = "test_obj_malformed.obj"; + + const std::string header = + "v 0.0 0.0 0.0\n" + "v 1.0 0.0 0.0\n" + "v 0.0 1.0 0.0\n" + "vn 0.0 0.0 1.0\n" + "vt 0.0 0.0\n" + "usemtl None\n"; + + const std::vector bad_faces = { + "f 4//1 2//1 3//1\n", + "f 999999//1 2//1 3//1\n", + "f 1//999999 2//1 3//1\n", + "f 0//1 2//1 3//1\n", + "f -999//1 2//1 3//1\n", + "f abc//1 2//1 3//1\n", + "f 99999999999//1 2//1 3//1\n", + }; + + for (const auto &bad_face : bad_faces) + { + std::ofstream fs (fname); + fs << header << bad_face; + fs.close (); + + pcl::OBJReader objreader; + + pcl::PCLPointCloud2 blob; + EXPECT_EQ (objreader.read (fname, blob), -1) << "blob reader accepted: " << bad_face; + + pcl::PolygonMesh poly_mesh; + EXPECT_EQ (objreader.read (fname, poly_mesh), -1) << "PolygonMesh reader accepted: " << bad_face; + + pcl::TextureMesh tex_mesh; + EXPECT_EQ (objreader.read (fname, tex_mesh), -1) << "TextureMesh reader accepted: " << bad_face; + } + + { + std::ofstream fs (fname); + fs << header << "f 1/999999/1 2/1/1 3/1/1\n"; + fs.close (); + + pcl::OBJReader objreader; + pcl::TextureMesh tex_mesh; + EXPECT_EQ (objreader.read (fname, tex_mesh), -1); + } + + remove (fname.c_str ()); +} + +TEST(PCL, OBJReadValidRelativeIndices) +{ + const std::string fname = "test_obj_relative.obj"; + std::ofstream fs (fname); + fs << "v 0.0 0.0 0.0\n" + "v 1.0 0.0 0.0\n" + "v 0.0 1.0 0.0\n" + "vn 0.0 0.0 1.0\n" + "f -3//-1 -2//-1 -1//-1\n"; + fs.close (); + + pcl::OBJReader objreader; + + pcl::PCLPointCloud2 blob; + EXPECT_EQ (objreader.read (fname, blob), 0); + EXPECT_EQ (blob.width, 3); + + pcl::PolygonMesh poly_mesh; + EXPECT_EQ (objreader.read (fname, poly_mesh), 0); + EXPECT_EQ (poly_mesh.polygons.size (), 1); + + remove (fname.c_str ()); +} + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// struct PointXYZFPFH33