CNA-BUG-131: The .cnj Model bones parser accepts forward or self parent indices and turns a malformed transform into identity

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.

ParseCnjBoneArrayEXT keeps a transform only when it has exactly 16 numbers and the bone loop checks only that a parent index is in range, so a bone can name a later bone (or itself) as parent and CopyAbsoluteBoneTransformsTo reads an uncomputed slot.

Identifier
CNA-BUG-131
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 with a bones array; Model::CopyAbsoluteBoneTransformsTo

Expected behaviour

Model::CopyAbsoluteBoneTransformsTo in Model.cpp assumes each parent precedes its child (it composes with dest[parentIdx] in index order), as XNA's does; AnimationPlayer refuses a hierarchy that is not topologically ordered. A loader should refuse a bone list that breaks that order or carries a malformed transform.

Actual behaviour at TARGET

ParseCnjBoneArrayEXT in ContentManager.cpp sets a bone's transform only when the array has exactly 16 numbers, leaving identity otherwise, without an error. The Model reader then checks only 0 <= parent < boneCount before AddChild, so a parent index equal to or greater than the child's is accepted; a self-parent makes the bone its own child. Absolute transforms then use a parent slot that has not been computed yet (the thread-local draw buffer's stale value in Model::Draw).

Source locations

Evidence

Checked by reading at 009d40f5; not executed.

Focused reproduction

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

Current tests

easygl_model_json_reader_bone_hierarchy_test.cpp and the .cnj tests load well-formed hierarchies; no test feeds a malformed bone list.

Regression test

Fixtures with a forward parent, a self parent and a 15-number transform, each expecting ContentLoadException.

Blast radius

.cnj Model documents written by hand or by other tools; gltf_to_cnj writes topologically ordered bones.

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