Skip to content

Check the inline range before casting style values to int32 - #2075

Open
ZainnQureshii wants to merge 1 commit into
react:mainfrom
ZainnQureshii:fix/style-value-range
Open

ZainnQureshii wants to merge 1 commit into
react:mainfrom
ZainnQureshii:fix/style-value-range

Conversation

@ZainnQureshii

Copy link
Copy Markdown

Summary

StyleValuePool::isIntegerPackable (yoga/style/StyleValuePool.h) casts the float to int32_t before checking that it fits the inline range:

auto i = static_cast<int32_t>(f);
return static_cast<float>(i) == f && i >= -kMaxInlineAbsValue &&
    i <= +kMaxInlineAbsValue;

Converting a float that is outside the int32_t range (or infinite, or NaN) to int32_t is undefined behaviour, and every newly stored style length, size or number whose handle is not already indexed into the buffer goes through this check, so a value such as 2147483648, FLT_MAX or an infinite number hits it. The fix checks the range on the float first and only then casts to test that the value is an integer, so the cast only ever sees values in -2047..2047. Values that fit are packed exactly as before.

No wrong layout is claimed for an ordinary build (checked with Apple Clang on arm64); the problem shows up under -fsanitize=float-cast-overflow, which aborts while storing those values.

Tests

Two new cases in tests/StyleValuePoolTest.cpp store out-of-range finite values (2147483648, -4294967296, ±FLT_MAX) as points, percent and numbers, and ±infinity as numbers, and read them back.

Built with -DCMAKE_CXX_FLAGS=-fsanitize=float-cast-overflow -fno-sanitize-recover=float-cast-overflow, both new tests abort before the fix and pass after it, and the full test binary passes with the fix. Without the sanitizer, the new tests pass both before and after.

Changelog:
[General][Fixed] - Fix undefined behavior in Yoga when storing style values outside the 32-bit integer range

Prepared with AI assistance (Claude Code) and reviewed with GitHub Copilot.

🤖 Generated with Claude Code

isIntegerPackable cast the float to int32_t before checking that it fits the inline range, which is undefined for values outside int32 (and for infinity and NaN). Check the range on the float first, then cast to test that it is an integer.
@meta-cla meta-cla Bot added the CLA Signed label Nov 10, 2026
@facebook-github-tools facebook-github-tools Bot added the Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. label Nov 10, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant