CNA-BUG-026: Matrix::CreatePerspectiveFieldOfView accepts a field of view of exactly MathHelper::Pi
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
modules/math/src/Matrix.cpp— Matrix::CreatePerspectiveFieldOfView(float, float, float, float, Matrix&): the 3.141593f guardmodules/math/include/Microsoft/Xna/Framework/MathHelper.hpp— MathHelper::Pi = 3.14159274fmodules/math/tests/Microsoft/Xna/Framework/MatrixTests.cpp— MatrixTest.CreatePerspectiveFieldOfViewThrowsBadFov tests only a zero field of view
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.
Related pages
The same subject is explained at several altitudes. These are the neighbouring pages at each one.
- User guide
- Math types: Matrix
- Maintainer workflow
- Add a regression test: the math case
- Known issues
- Bug index