CNA-BUG-129: BlendMorphTargetsEXT indexes NormalDeltas and every per-vertex delta array without checking their lengths

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.

The function validates only the weight count; a hand-built MorphTargetDataEXT whose NormalDeltas has fewer entries than targets, or whose delta arrays are shorter than the vertex count, is read out of range.

Identifier
CNA-BUG-129
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
Microsoft::Xna::Framework::Graphics::BlendMorphTargetsEXT(const MorphTargetDataEXT&, const std::vector<float>&) and ApplyMorphWeightsEXT

Expected behaviour

BlendMorphTargetsEXT is a public CNAEXT function that already validates its input (it throws when the weight count differs from the target count). Inconsistent morph data should likewise be refused, not read out of range; the same function guards TangentDeltas with t < TangentDeltas.size().

Actual behaviour at TARGET

In MorphTargetEXT.cpp the loop reads morph.NormalDeltas[t] for every weighted target with no check of the outer size, and reads PositionDeltas[t][v], NormalDeltas[t][v] and TangentDeltas[t][v] for every vertex of BaseVertexBytes whenever the inner vector is non-empty, without checking it holds that many elements. MorphTargetEXT.hpp describes the arrays as per-target, per-vertex but states no precondition. The importers always build consistent arrays, so only application-built data reaches the out-of-range reads.

Source locations

Evidence

Checked by reading at 009d40f5; not executed.

Focused reproduction

// Illustrative; not compiled or run.
MorphTargetDataEXT morph;
morph.Stride = 12;
morph.BaseVertexBytes.resize(12 * 3);        // three vertices
morph.PositionDeltas = {std::vector<Vector3>(3)};  // one target
// NormalDeltas left empty: NormalDeltas[0] is out of range
auto bytes = BlendMorphTargetsEXT(morph, {1.0f});

Current tests

MorphTargetEXTTests.cpp blends consistent data only; no test passes short or missing delta arrays.

Regression test

Cases with a missing NormalDeltas entry and a delta array shorter than the vertex count, expecting an exception (the weight-count check already sets the pattern).

Blast radius

Applications that build MorphTargetDataEXT by hand. Imported glTF, .cnj and .cnb morph targets are consistent by construction.

Workaround

Give NormalDeltas and TangentDeltas one (possibly empty) entry per target and size every non-empty delta array to the vertex count.

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

Known issues
Bug index