CNA-BUG-026: Matrix::CreatePerspectiveFieldOfView accepts a field of view of exactly MathHelper::Pi

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 upper guard compares against the literal 3.141593f, which rounds to the float one step above MathHelper::Pi, so a field of view of exactly Pi passes validation and builds a degenerate projection instead of throwing as XNA does.

Identifier
CNA-BUG-026
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
Matrix::CreatePerspectiveFieldOfView(float fieldOfView, float aspectRatio, float nearPlaneDistance, float farPlaneDistance) and its output-parameter form; C ABI cna_matrix_create_perspective_field_of_view

Expected behaviour

A field of view must be strictly between 0 and π. XNA 4.0's guard compares against 3.14159274f, which is exactly MathHelper.Pi, and throws for fieldOfView >= Pi (read from the IL of the genuine XNA 4.0 Microsoft.Xna.Framework assembly; not executed). CNA's own message states the same rule: "fieldOfView <= 0 or >= PI".

Actual behaviour at TARGET

Matrix.cpp tests fieldOfView >= 3.141593f. The decimal literal rounds to the single-precision value 3.14159298 (0x40490FDC), one step above MathHelper::Pi = 3.14159274 (0x40490FDB), so CreatePerspectiveFieldOfView(MathHelper::Pi, …) passes. 1.0f / std::tan(fieldOfView * 0.5f) then evaluates the tangent just past π/2, a large negative number, so M22 and M11 become tiny negative values (about -4.4e-8): the projection flips and collapses the image instead of throwing. Exactly one float value is admitted; FNA uses the same literal.

Separately, the thrown type is std::invalid_argument where XNA throws ArgumentOutOfRangeException; that is part of the mixed exception families recorded in its own entry.

Source locations

Evidence

Checked by reading at 009d40f5; nothing was built or executed for this entry. The IEEE-754 single-precision rounding of the literal and of π, and the tangent value quoted above, were computed outside CNA (in double precision from the float argument); CNA itself was not built or run. The XNA constant was read from its IL, where the same assembly declares MathHelper.Pi as 3.14159274.

Focused reproduction

Illustrative; not compiled or run for this entry.

Matrix m;
EXPECT_THROW(Matrix::CreatePerspectiveFieldOfView(MathHelper::Pi, 1.0f, 1.0f, 100.0f, m),
             std::invalid_argument);          // fails at TARGET: nothing is thrown

Current tests

MatrixTest.CreatePerspectiveFieldOfViewThrowsBadFov in MatrixTests.cpp covers only fieldOfView = 0; no test touches the upper bound. The C ABI smoke test uses valid values only.

Regression test

Expect the exception at MathHelper::Pi and at std::nextafter(MathHelper::Pi, 4.0f), and no exception at std::nextafter(MathHelper::Pi, 0.0f). The fix is to compare against MathHelper::Pi itself.

Blast radius

Only CreatePerspectiveFieldOfView (both overloads) and its C ABI route, and only for the single input value π; a caller passing it gets a degenerate matrix instead of an error.

Workaround

Keep the field of view below MathHelper::Pi before calling; a field of view that wide is unusable anyway.

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

Known issues
Bug index