Fix undefined double-to-int cast in lexer_construct_number_object (#5304) - #5308
Open
1820893135-pixel wants to merge 1 commit into
Open
1820893135-pixel wants to merge 1 commit into
1820893135-pixel wants to merge 1 commit into
Conversation
lexer_construct_number_object() tries to fold a numeric literal into a
CBC_PUSH_NUMBER_BYTE_RANGE immediate by casting the parsed double to
int32_t and then checking whether the cast round-trips:
int32_t int_num = (int32_t) num;
if (int_num == num && ...)
For a literal outside the int32_t range the cast itself is already
undefined behaviour; it is not the comparison that guards it. Under
-fsanitize=undefined (the OSS-Fuzz configuration) this traps:
js-lexer.c:2539:25: runtime error: 1e+308 is outside the range of
representable values of type 'int'
The input is plain, valid JavaScript, so any host that evaluates
untrusted source (jerry_parse / jerry_eval) deterministically aborts:
`var a = 1e308;` is enough.
Move the range test in front of the cast:
if (is_expr && num >= (ecma_number_t) INT32_MIN
&& num <= (ecma_number_t) INT32_MAX)
{
int32_t int_num = (int32_t) num;
...
Literals outside the range simply take the float path, which is what
already happened for every value the fold did not apply to.
JerryScript-DCO-1.0-Signed-off-by: 1820893135-pixel <1820893135@qq.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
lexer_construct_number_object()tries to fold a numeric literal into aCBC_PUSH_NUMBER_BYTE_RANGEimmediate by casting the parsed double toint32_tand then checking whether the cast round-trips (js-lexer.c:2539):For a literal outside the
int32_trange the cast itself is already undefinedbehaviour - the comparison afterwards is too late to guard it. Under
-fsanitize=undefined(the OSS-Fuzz configuration) it traps:The trigger is plain, valid JavaScript - no malformed input involved:
Reachable through
jerry_parse/jerry_eval, so any embedder that evaluatesuntrusted source deterministically aborts a UBSan build.
Fix
Move the range test in front of the cast:
Literals outside the range simply take the float path, which is exactly what
already happened for every value the fold did not apply to.
Testing
Adds
tests/jerry/number-literal-range.jscovering literals on both sides ofthe boundary. On an unpatched
-fsanitize=undefinedbuild the new file abortswith the report above; with the fix it passes.
Fixes #5304.