Skip to content

[io] validate vertex lines in OBJReader::read - #6493

Merged
mvieth merged 2 commits into
PointCloudLibrary:masterfrom
aysha-afrah26:obj-vertex-line-bounds
Oct 28, 2026
Merged

mvieth merged 2 commits into
PointCloudLibrary:masterfrom
aysha-afrah26:obj-vertex-line-bounds

Conversation

@aysha-afrah26

Copy link
Copy Markdown
Contributor

AddressSanitizer, OBJReader::read (file, PCLPointCloud2&) on a file containing v 0 0 0 followed by v\t1 2 3:

ERROR: AddressSanitizer: heap-buffer-overflow
WRITE of size 4 at 0x60200000095c thread T0
    #0 in pcl::OBJReader::read(..., pcl::PCLPointCloud2&, ...) obj_io.cpp:597
0x60200000095c is located 0 bytes after 12-byte region

readHeader sizes cloud.data from the lines it counts as vertices, and it only counts a line when line[1] == ' '. The body loops of all three read overloads tokenise on tab, CR and space instead, so a vertex line separated by a tab or carriage return is missing from the count but still written at v_idx * point_step, past the end of cloud.data. The PolygonMesh and TextureMesh overloads fail the same way (obj_io.cpp:1079 and :813 before the patch). The same loops also read st[1..3] on v and vn lines without checking the token count (v 1 2 is an out-of-bounds read under ASan), and the TextureMesh vt loop stores every token into an Eigen::Vector3f, so a vt line with more than three values writes past it in release builds.

Each v line is now checked against the header count and its token count before the write, short vn lines are rejected, the vt loop stops after three values, and readHeader also counts tab separated vertices so those files load instead of being rejected. This complements the face index checks from #6448, which covered f lines but not the vertex lines that fill cloud.data. The new OBJReadMalformedVertexLines test fails under ASan before the patch and passes after; I ran it together with the existing OBJ tests from test_io.cpp against obj_io.cpp in a standalone ASan build.

readHeader sizes cloud.data from the lines it counts as vertices, but the
read overloads also store a "v" line separated by a tab or carriage
return, writing past the end of cloud.data. Reject vertex lines beyond
the header count or with fewer than three coordinates, reject short
vertex normal lines, cap the texture coordinate loop at three values, and
count tab separated vertices in readHeader so such files keep loading.
Comment thread io/src/obj_io.cpp Outdated
{
Eigen::Vector3f c (0, 0, 0);
for (std::size_t i = 1; i < st.size (); ++i)
for (std::size_t i = 1; i < st.size () && i < 4; ++i)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason why you chose to not error-out here if st.size() > 4? E.g. vt 1.0 2.0 3.0 4.0 is invalid obj format, right? Might be better to display an error and quit, instead of silently ignoring the extra values?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No strong reason, I was only after the out-of-bounds write. You're right that vt takes at most u, v, w, so it now prints an error and returns -1 when there are more than three values, the same way the short v/vn lines are handled. Updated the test so vt 0.0 0.0 1.0 1.0 is expected to fail for the TextureMesh reader.

@mvieth mvieth left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@mvieth
mvieth merged commit 67ef046 into PointCloudLibrary:master Oct 28, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants