CNA-BUG-130: The .cnj Model reader truncates vertex and index sidecar sizes and never range-checks indices, where the SkinnedModel reader refuses the same input

CNA snapshot 009d40f5  ·  Known Issues › Current bugs  ·  source links pinned to 009d40f5

✓

Evidence basis: source-verified at the pinned commit; tests exist (not executed for this page). Claims on this page were checked by reading the CNA source at commit 009d40f5; unless a sentence says otherwise, nothing here was built or executed. Nothing on this page was executed unless the Evidence section says so.

ModelTypeReader and BuildModelMeshPartGeometryEXT derive vertex and index counts by integer division, discarding trailing bytes, and build the index buffer without checking indices against the vertex count; the SkinnedModel reader in the same file throws ContentLoadException for both. A mesh with a non-positive vertexStride is silently skipped, as it is in the SkinnedModel reader.

Identifier
CNA-BUG-130
Category
Bug
Subsystem
Models & glTF
Status
Open
Verified against
CNA 009d40f5 (009d40f5dd085c4e674d3479675fac84b12b3e0a)
Severity
Low (a triage suggestion, not a project priority)
Evidence basis
Source-verified: read at TARGET, not executed
Tests touching this area
Yes: see Current tests
Affected contract
ContentManager::Load<Model> on .cnj Model documents (ModelTypeReader, BuildModelMeshPartGeometryEXT)

Expected behaviour

A malformed Model descriptor should be refused with ContentLoadException. The same file's SkinnedModel reader does this deliberately (Task 11.9): it throws when the vertex data is not a multiple of vertexStride or the index data not a multiple of the index size, and checks every index against the vertex count.

Actual behaviour at TARGET

In ContentManager.cpp the Model reader's mesh loop computes numVertices = size / stride, and BuildModelMeshPartGeometryEXT divides the vertex and index byte counts likewise, dropping any remainder, and builds the index buffer without checking indices against the vertex count, so a corrupt sidecar yields a truncated mesh or indices that reference missing vertices. Both the Model and SkinnedModel readers silently skip a mesh whose vertexStride is zero or negative (and one with no vertices or indices file); that skip is not a divergence between them.

Source locations

Evidence

Checked by reading at 009d40f5; not executed.

Independent re-verification: Checked by reading at 009d40f5; not executed. Correction: the original wording listed the stride skip as something the SkinnedModel reader refuses; it does not, both use `continue`.

Focused reproduction

No focused reproduction is known. Nothing has been invented here; the evidence above is what exists.

Current tests

The .cnj Model tests (and the EasyGL easygl_model_json_reader_* programs) use well-formed sidecars; no test feeds a bad stride or a truncated sidecar.

Regression test

Model .cnj fixtures with vertexStride: 0, a vertex sidecar one byte short and an out-of-range index, each expecting ContentLoadException; the fix is to reuse the SkinnedModel reader's checks.

Blast radius

.cnj Model documents written by hand or by other tools. Files written by gltf_to_cnj are consistent.

Workaround

No workaround is known.

The same subject is explained at several altitudes. These are the neighbouring pages at each one.

Known issues
Bug index