CNA-BUG-076: Color::FromNonPremultiplied(int r, int g, int b, int a) multiplies in 32-bit int, so large arguments overflow (undefined behaviour)
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.
CNA computes r * a / 255 in int; XNA 4.0 widens to 64-bit long before multiplying and clamps the result, so arguments whose product exceeds INT_MAX are defined in XNA and undefined in CNA.
- Identifier
CNA-BUG-076- Category
- Bug
- Subsystem
- Math & geometry
- 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::Color::FromNonPremultiplied(intcs r, intcs g, intcs b, intcs a)
Expected behaviour
XNA 4.0 (IL): each channel is ClampToByte64((long)r * a / 255) - conv.i8 on both operands, a 64-bit multiply and divide, then a clamp.
Actual behaviour at TARGET
Color.cpp computes static_cast<intcs>(r * a / ByteMax) with intcs operands. For in-range byte values this matches; for out-of-range inputs whose product exceeds INT_MAX (for example r = a = 50000) the multiplication overflows.
Source locations
modules/math/src/Color.cpp— Color::FromNonPremultiplied(intcs, intcs, intcs, intcs)
Evidence
Checked by reading the named sources at 009d40f5; nothing was built or executed for this entry. XNA arithmetic from the genuine XNA 4.0 IL.
Focused reproduction
No focused reproduction is known. Nothing has been invented here; the evidence above is what exists.
Current tests
ColorTests.cpp uses byte-range inputs.
Regression test
A test with FromNonPremultiplied(50000, 0, 0, 50000) expecting XNA's clamped (255, 0, 0, 255).
Blast radius
Only callers that pass values far outside 0-255; ordinary colour code is unaffected.
Workaround
Clamp arguments to 0-255 before the call.
Related pages
The same subject is explained at several altitudes. These are the neighbouring pages at each one.
- Known issues
- Bug index