Skip to content

[io] Fix out-of-bounds read/write when parsing OBJ face indices#6448

Open
jamestiotio wants to merge 1 commit into
PointCloudLibrary:masterfrom
jamestiotio:master
Open

[io] Fix out-of-bounds read/write when parsing OBJ face indices#6448
jamestiotio wants to merge 1 commit into
PointCloudLibrary:masterfrom
jamestiotio:master

Conversation

@jamestiotio

Copy link
Copy Markdown

The OBJ reader used the vertex, normal and texture-coordinate indices taken verbatim from a face ("f") line to index fixed-size vectors with no bounds checking, most importantly normal_mapping[v] += normals[n]. These indices are fully controlled by the input file, so a crafted face such as f 999999//1 turned that line into a read-modify-write of an Eigen::Vector3f at an arbitrary heap offset, and a short or empty normal list produced out-of-bounds reads.

Malformed numeric tokens were a second problem: std::stoi throws std::invalid_argument/std::out_of_range, neither of which the surrounding catch (const char*) handled, so a bad file aborted the caller with an uncaught exception.

Validate each index against its container's size (and guard the empty normal case) before use, erroring out cleanly when out of range, and broaden the handler to std::exception so unparsable indices fail the read instead of crashing. All three read overloads (PCLPointCloud2, PolygonMesh, TextureMesh) are fixed. Regression tests cover the rejected malformed faces and confirm that valid relative (negative) indices still load.

The OBJ reader used the vertex, normal and texture-coordinate indices
taken verbatim from a face ("f") line to index fixed-size vectors with
no bounds checking, most importantly `normal_mapping[v] += normals[n]`.
These indices are fully controlled by the input file, so a crafted face
such as `f 999999//1` turned that line into a read-modify-write of an
Eigen::Vector3f at an arbitrary heap offset, and a short or empty
normal list produced out-of-bounds reads.

Malformed numeric tokens were a second problem: std::stoi throws
std::invalid_argument/std::out_of_range, neither of which the
surrounding `catch (const char*)` handled, so a bad file aborted the
caller with an uncaught exception.

Validate each index against its container's size (and guard the
empty normal case) before use, erroring out cleanly when out of range,
and broaden the handler to std::exception so unparsable indices fail
the read instead of crashing. All three read overloads (PCLPointCloud2,
PolygonMesh, TextureMesh) are fixed. Regression tests cover the
rejected malformed faces and confirm that valid relative (negative)
indices still load.

Signed-off-by: James Raphael Tiovalen <jamestiotio@meta.com>

@larshg larshg left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good 👍

@larshg larshg added module: io changelog: fix Meta-information for changelog generation labels Jun 9, 2026
@larshg larshg added this to the pcl-1.16.0 milestone Jun 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog: fix Meta-information for changelog generation module: io

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants