Skip to content

Commit d852a3c

Browse files
Fix of ToUInt32 (ecma_number_to_uint32) and ToInt32 (ecma_number_to_int32) conversion routines.
Related issue: #160 JerryScript-DCO-1.0-Signed-off-by: Ruben Ayrapetyan [email protected]
1 parent 1a3940c commit d852a3c

File tree

1 file changed

+67
-14
lines changed

1 file changed

+67
-14
lines changed

jerry-core/ecma/base/ecma-helpers-conversion.cpp

Lines changed: 67 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -823,24 +823,60 @@ ecma_int32_to_number (int32_t value) /**< signed 32-bit integer value */
823823
} /* ecma_int32_to_number */
824824

825825
/**
826-
* ECMA-defined conversion of Number value to Uint32 value
826+
* ECMA-defined conversion of Number value to UInt32 value
827827
*
828828
* See also:
829829
* ECMA-262 v5, 9.6
830830
*
831-
* @return number - result of conversion.
831+
* @return 32-bit unsigned integer - result of conversion.
832832
*/
833833
uint32_t
834-
ecma_number_to_uint32 (ecma_number_t value) /**< unsigned 32-bit integer value */
834+
ecma_number_to_uint32 (ecma_number_t num) /**< ecma-number */
835835
{
836-
if (ecma_number_is_nan (value)
837-
|| ecma_number_is_zero (value)
838-
|| ecma_number_is_infinity (value))
836+
if (ecma_number_is_nan (num)
837+
|| ecma_number_is_zero (num)
838+
|| ecma_number_is_infinity (num))
839839
{
840840
return 0;
841841
}
842842

843-
return (uint32_t) value;
843+
bool sign = ecma_number_is_negative (num);
844+
ecma_number_t abs_num;
845+
846+
if (sign)
847+
{
848+
abs_num = ecma_number_negate (num);
849+
}
850+
else
851+
{
852+
abs_num = num;
853+
}
854+
855+
// 2 ^ 32
856+
const uint64_t uint64_2_pow_32 = (1ull << 32);
857+
858+
const ecma_number_t num_2_pow_32 = (float) uint64_2_pow_32;
859+
860+
ecma_number_t num_in_uint32_range = ecma_number_calc_remainder (abs_num,
861+
num_2_pow_32);
862+
863+
uint64_t uint64_num = (uint64_t) num_in_uint32_range;
864+
865+
uint64_t ret;
866+
867+
if (sign)
868+
{
869+
ret = uint64_2_pow_32 - uint64_num;
870+
}
871+
else
872+
{
873+
ret = uint64_num;
874+
}
875+
876+
// Check that the value can be represented with uint32_t
877+
JERRY_ASSERT (ret < (1ull << 32));
878+
879+
return (uint32_t) ret;
844880
} /* ecma_number_to_uint32 */
845881

846882
/**
@@ -849,19 +885,36 @@ ecma_number_to_uint32 (ecma_number_t value) /**< unsigned 32-bit integer value *
849885
* See also:
850886
* ECMA-262 v5, 9.5
851887
*
852-
* @return number - result of conversion.
888+
* @return 32-bit signed integer - result of conversion.
853889
*/
854890
int32_t
855-
ecma_number_to_int32 (ecma_number_t value) /**< unsigned 32-bit integer value */
891+
ecma_number_to_int32 (ecma_number_t num) /**< ecma-number */
856892
{
857-
if (ecma_number_is_nan (value)
858-
|| ecma_number_is_zero (value)
859-
|| ecma_number_is_infinity (value))
893+
int64_t int64_num = ecma_number_to_uint32 (num);
894+
895+
// 2 ^ 32
896+
const int64_t int64_2_pow_32 = (1ll << 32);
897+
898+
// 2 ^ 31
899+
const int64_t int64_2_pow_31 = (1ll << 31);
900+
901+
JERRY_ASSERT (int64_num >= 0);
902+
903+
int64_t ret;
904+
905+
if (int64_num >= int64_2_pow_31)
860906
{
861-
return 0;
907+
ret = (int64_num - int64_2_pow_32);
862908
}
909+
else
910+
{
911+
ret = int64_num;
912+
}
913+
914+
// Check that the value can be represented with int32_t
915+
JERRY_ASSERT (ret >= -int64_2_pow_31 && ret < int64_2_pow_31);
863916

864-
return (int32_t) (uint32_t) value;
917+
return (int32_t) ret;
865918
} /* ecma_number_to_int32 */
866919

867920
#if CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT64

0 commit comments

Comments
 (0)