From f03f55ac478ec5d0c451f484ebaedbc414484f82 Mon Sep 17 00:00:00 2001 From: Yonggang Luo Date: Tue, 10 Dec 2024 15:24:57 +0800 Subject: [PATCH] Fixes ecma_uint32_to_utf8_string that fill \0 at the end of string Closes: #5194 JerryScript-DCO-1.0-Signed-off-by: Yonggang Luo luoyonggang@gmail.com --- jerry-core/api/jerry-snapshot.c | 6 ++-- jerry-core/ecma/base/ecma-globals.h | 5 +++ .../ecma/base/ecma-helpers-conversion.c | 10 +++--- jerry-core/ecma/base/ecma-helpers-string.c | 36 +++++++++---------- jerry-core/ecma/base/ecma-helpers.h | 1 + .../ecma-builtin-number-prototype.c | 2 +- tests/unit-core/test-number-to-string.c | 12 +++++++ 7 files changed, 46 insertions(+), 26 deletions(-) diff --git a/jerry-core/api/jerry-snapshot.c b/jerry-core/api/jerry-snapshot.c index 33760b299f..6478193309 100644 --- a/jerry-core/api/jerry-snapshot.c +++ b/jerry-core/api/jerry-snapshot.c @@ -1507,11 +1507,11 @@ jerry_append_number_to_buffer (uint8_t *buffer_p, /**< buffer */ uint8_t *buffer_end_p, /**< the end of the buffer */ lit_utf8_size_t number) /**< number */ { - lit_utf8_byte_t uint32_to_str_buffer[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32]; + lit_utf8_byte_t uint32_to_str_buffer[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32_WITH_ZERO_TERMINATED]; lit_utf8_size_t utf8_str_size = - ecma_uint32_to_utf8_string (number, uint32_to_str_buffer, ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); + ecma_uint32_to_utf8_string (number, uint32_to_str_buffer, ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32_WITH_ZERO_TERMINATED); - JERRY_ASSERT (utf8_str_size <= ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); + JERRY_ASSERT (utf8_str_size < ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32_WITH_ZERO_TERMINATED); return jerry_append_chars_to_buffer (buffer_p, buffer_end_p, diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index 75c70e196b..521c206b63 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -1379,6 +1379,11 @@ typedef float ecma_number_t; */ #define ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32 10 +/** + * Maximum number of characters in string representation of ecma-uint32 + */ +#define ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32_WITH_ZERO_TERMINATED (ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32 + 1) + /** * String is not a valid array index. */ diff --git a/jerry-core/ecma/base/ecma-helpers-conversion.c b/jerry-core/ecma/base/ecma-helpers-conversion.c index db22503a69..f0e5a0570f 100644 --- a/jerry-core/ecma/base/ecma-helpers-conversion.c +++ b/jerry-core/ecma/base/ecma-helpers-conversion.c @@ -659,7 +659,8 @@ ecma_uint32_to_utf8_string (uint32_t value, /**< value to convert */ lit_utf8_byte_t *out_buffer_p, /**< buffer for string */ lit_utf8_size_t buffer_size) /**< size of buffer */ { - lit_utf8_byte_t *buf_p = out_buffer_p + buffer_size; + lit_utf8_byte_t *buf_p_tail = out_buffer_p + buffer_size - 1; + lit_utf8_byte_t *buf_p = buf_p_tail; do { @@ -672,12 +673,13 @@ ecma_uint32_to_utf8_string (uint32_t value, /**< value to convert */ JERRY_ASSERT (buf_p >= out_buffer_p); - lit_utf8_size_t bytes_copied = (lit_utf8_size_t) (out_buffer_p + buffer_size - buf_p); + lit_utf8_size_t bytes_copied = (lit_utf8_size_t) (buf_p_tail - buf_p); if (JERRY_LIKELY (buf_p != out_buffer_p)) { memmove (out_buffer_p, buf_p, bytes_copied); } + buf_p[bytes_copied] = '\0'; return bytes_copied; } /* ecma_uint32_to_utf8_string */ @@ -865,7 +867,7 @@ ecma_number_to_utf8_string (ecma_number_t num, /**< ecma-number */ if (((ecma_number_t) num_uint32) == num) { dst_p += ecma_uint32_to_utf8_string (num_uint32, dst_p, (lit_utf8_size_t) (buffer_p + buffer_size - dst_p)); - JERRY_ASSERT (dst_p <= buffer_p + buffer_size); + JERRY_ASSERT (dst_p < buffer_p + buffer_size); return (lit_utf8_size_t) (dst_p - buffer_p); } @@ -932,7 +934,7 @@ ecma_number_to_utf8_string (ecma_number_t num, /**< ecma-number */ dst_p += ecma_uint32_to_utf8_string (t, dst_p, (lit_utf8_size_t) (buffer_p + buffer_size - dst_p)); - JERRY_ASSERT (dst_p <= buffer_p + buffer_size); + JERRY_ASSERT (dst_p < buffer_p + buffer_size); return (lit_utf8_size_t) (dst_p - buffer_p); } /* ecma_number_to_utf8_string */ diff --git a/jerry-core/ecma/base/ecma-helpers-string.c b/jerry-core/ecma/base/ecma-helpers-string.c index 449410a3ee..f61ff438c7 100644 --- a/jerry-core/ecma/base/ecma-helpers-string.c +++ b/jerry-core/ecma/base/ecma-helpers-string.c @@ -726,7 +726,7 @@ ecma_append_chars_to_string (ecma_string_t *string1_p, /**< base ecma-string */ lit_utf8_size_t cesu8_string1_size; lit_utf8_size_t cesu8_string1_length; uint8_t flags = ECMA_STRING_FLAG_IS_ASCII; - lit_utf8_byte_t uint32_to_string_buffer[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32]; + lit_utf8_byte_t uint32_to_string_buffer[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32_WITH_ZERO_TERMINATED]; const lit_utf8_byte_t *cesu8_string1_p = ecma_string_get_chars (string1_p, &cesu8_string1_size, &cesu8_string1_length, uint32_to_string_buffer, &flags); @@ -831,7 +831,7 @@ ecma_concat_ecma_strings (ecma_string_t *string1_p, /**< first ecma-string */ lit_utf8_size_t cesu8_string2_size; lit_utf8_size_t cesu8_string2_length; - lit_utf8_byte_t uint32_to_string_buffer[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32]; + lit_utf8_byte_t uint32_to_string_buffer[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32_WITH_ZERO_TERMINATED]; uint8_t flags = ECMA_STRING_FLAG_IS_ASCII; const lit_utf8_byte_t *cesu8_string2_p = @@ -1081,8 +1081,8 @@ ecma_uint32_to_buffer (uint32_t num, /**< number */ lit_utf8_byte_t *buffer_p /**< destination buffer */, lit_utf8_size_t buffer_size /**< buffer size */) { - lit_utf8_byte_t digits[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32]; - lit_utf8_size_t digit_count = ecma_uint32_to_utf8_string (num, digits, ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); + lit_utf8_byte_t digits[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32_WITH_ZERO_TERMINATED]; + lit_utf8_size_t digit_count = ecma_uint32_to_utf8_string (num, digits, ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32_WITH_ZERO_TERMINATED); digit_count = JERRY_MIN (buffer_size, digit_count); memcpy (buffer_p, digits, digit_count); @@ -1192,7 +1192,7 @@ ecma_string_to_cesu8_bytes (const ecma_string_t *string_desc_p, /**< ecma-string * * @return size in bytes */ -static inline lit_utf8_size_t JERRY_ATTR_ALWAYS_INLINE +extern inline lit_utf8_size_t JERRY_ATTR_ALWAYS_INLINE ecma_string_get_uint32_size (const uint32_t uint32_number) /**< number in the string-descriptor */ { uint32_t prev_number = 1; @@ -1292,11 +1292,11 @@ ecma_string_get_chars (const ecma_string_t *string_p, /**< ecma-string */ } else { - result_p = (const lit_utf8_byte_t *) jmem_heap_alloc_block (size); + result_p = (const lit_utf8_byte_t *) jmem_heap_alloc_block (size + 1); *flags_p |= ECMA_STRING_FLAG_MUST_BE_FREED; } - length = ecma_uint32_to_utf8_string (uint32_number, (lit_utf8_byte_t *) result_p, size); + length = ecma_uint32_to_utf8_string (uint32_number, (lit_utf8_byte_t *) result_p, size + 1); JERRY_ASSERT (length == size); *flags_p |= ECMA_STRING_FLAG_IS_UINT32; @@ -1343,11 +1343,11 @@ ecma_string_get_chars (const ecma_string_t *string_p, /**< ecma-string */ } else { - result_p = (const lit_utf8_byte_t *) jmem_heap_alloc_block (size); + result_p = (const lit_utf8_byte_t *) jmem_heap_alloc_block (size + 1); *flags_p |= ECMA_STRING_FLAG_MUST_BE_FREED; } - length = ecma_uint32_to_utf8_string (string_p->u.uint32_number, (lit_utf8_byte_t *) result_p, size); + length = ecma_uint32_to_utf8_string (string_p->u.uint32_number, (lit_utf8_byte_t *) result_p, size + 1); JERRY_ASSERT (length == size); *flags_p |= ECMA_STRING_FLAG_IS_UINT32 | ECMA_STRING_FLAG_REHASH_NEEDED; @@ -1716,8 +1716,8 @@ ecma_compare_ecma_strings_relational (const ecma_string_t *string1_p, /**< ecma- const lit_utf8_byte_t *utf8_string1_p, *utf8_string2_p; lit_utf8_size_t utf8_string1_size, utf8_string2_size; - lit_utf8_byte_t uint32_to_string_buffer1[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32]; - lit_utf8_byte_t uint32_to_string_buffer2[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32]; + lit_utf8_byte_t uint32_to_string_buffer1[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32_WITH_ZERO_TERMINATED]; + lit_utf8_byte_t uint32_to_string_buffer2[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32_WITH_ZERO_TERMINATED]; if (ECMA_IS_DIRECT_STRING (string1_p)) { @@ -1729,7 +1729,7 @@ ecma_compare_ecma_strings_relational (const ecma_string_t *string1_p, /**< ecma- { utf8_string1_size = ecma_uint32_to_utf8_string ((uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string1_p), uint32_to_string_buffer1, - ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); + ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32_WITH_ZERO_TERMINATED); utf8_string1_p = uint32_to_string_buffer1; } } @@ -1745,7 +1745,7 @@ ecma_compare_ecma_strings_relational (const ecma_string_t *string1_p, /**< ecma- { utf8_string1_size = ecma_uint32_to_utf8_string (string1_p->u.uint32_number, uint32_to_string_buffer1, - ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); + ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32_WITH_ZERO_TERMINATED); utf8_string1_p = uint32_to_string_buffer1; } } @@ -1760,7 +1760,7 @@ ecma_compare_ecma_strings_relational (const ecma_string_t *string1_p, /**< ecma- { utf8_string2_size = ecma_uint32_to_utf8_string ((uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string2_p), uint32_to_string_buffer2, - ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); + ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32_WITH_ZERO_TERMINATED); utf8_string2_p = uint32_to_string_buffer2; } } @@ -1776,7 +1776,7 @@ ecma_compare_ecma_strings_relational (const ecma_string_t *string1_p, /**< ecma- { utf8_string2_size = ecma_uint32_to_utf8_string (string2_p->u.uint32_number, uint32_to_string_buffer2, - ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); + ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32_WITH_ZERO_TERMINATED); utf8_string2_p = uint32_to_string_buffer2; } } @@ -2061,7 +2061,7 @@ ecma_string_get_char_at_pos (const ecma_string_t *string_p, /**< ecma-string */ { JERRY_ASSERT (index < ecma_string_get_length (string_p)); - lit_utf8_byte_t uint32_to_string_buffer[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32]; + lit_utf8_byte_t uint32_to_string_buffer[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32_WITH_ZERO_TERMINATED]; if (ECMA_IS_DIRECT_STRING (string_p)) { @@ -2086,7 +2086,7 @@ ecma_string_get_char_at_pos (const ecma_string_t *string_p, /**< ecma-string */ JERRY_ASSERT (ECMA_GET_DIRECT_STRING_TYPE (string_p) == ECMA_DIRECT_STRING_UINT); uint32_t uint32_number = (uint32_t) ECMA_GET_DIRECT_STRING_VALUE (string_p); - ecma_uint32_to_utf8_string (uint32_number, uint32_to_string_buffer, ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); + ecma_uint32_to_utf8_string (uint32_number, uint32_to_string_buffer, ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32_WITH_ZERO_TERMINATED); return (ecma_char_t) uint32_to_string_buffer[index]; } @@ -2132,7 +2132,7 @@ ecma_string_get_char_at_pos (const ecma_string_t *string_p, /**< ecma-string */ { ecma_uint32_to_utf8_string (string_p->u.uint32_number, uint32_to_string_buffer, - ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32); + ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32_WITH_ZERO_TERMINATED); return (ecma_char_t) uint32_to_string_buffer[index]; } diff --git a/jerry-core/ecma/base/ecma-helpers.h b/jerry-core/ecma/base/ecma-helpers.h index 0e98ea243b..cc41c0befa 100644 --- a/jerry-core/ecma/base/ecma-helpers.h +++ b/jerry-core/ecma/base/ecma-helpers.h @@ -508,6 +508,7 @@ ecma_number_t ecma_utf8_string_to_number_by_radix (const lit_utf8_byte_t *str_p, lit_utf8_size_t str_size, uint32_t radix, uint32_t option); +lit_utf8_size_t ecma_string_get_uint32_size (const uint32_t uint32_number); lit_utf8_size_t ecma_uint32_to_utf8_string (uint32_t value, lit_utf8_byte_t *out_buffer_p, lit_utf8_size_t buffer_size); uint32_t ecma_number_to_uint32 (ecma_number_t num); int32_t ecma_number_to_int32 (ecma_number_t num); diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-number-prototype.c b/jerry-core/ecma/builtin-objects/ecma-builtin-number-prototype.c index 1d212f5f7c..be57acc120 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-number-prototype.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-number-prototype.c @@ -525,7 +525,7 @@ ecma_builtin_number_prototype_object_to_number_convert (ecma_number_t this_num, } /* Append exponent part */ - lit_utf8_size_t exp_size = ecma_uint32_to_utf8_string ((uint32_t) exponent, digits, 3); + lit_utf8_size_t exp_size = ecma_uint32_to_utf8_string ((uint32_t) exponent, digits, 3 + 1); ecma_stringbuilder_append_raw (&builder, digits, exp_size); return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); diff --git a/tests/unit-core/test-number-to-string.c b/tests/unit-core/test-number-to-string.c index ed5fce2261..11494c8645 100644 --- a/tests/unit-core/test-number-to-string.c +++ b/tests/unit-core/test-number-to-string.c @@ -50,5 +50,17 @@ main (void) } } + lit_utf8_byte_t val_uint32_max_buffer[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32_WITH_ZERO_TERMINATED] = { 0 }; + memset (val_uint32_max_buffer, 0xFF, sizeof (val_uint32_max_buffer)); + + TEST_ASSERT(ecma_string_get_uint32_size(UINT32_MAX) == 10); + TEST_ASSERT(ecma_string_get_uint32_size(0) == 1); + TEST_ASSERT(ecma_string_get_uint32_size(10) == 2); + lit_utf8_size_t digits = ecma_uint32_to_utf8_string (UINT32_MAX, + val_uint32_max_buffer, + ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32_WITH_ZERO_TERMINATED); + TEST_ASSERT (digits == 10); + TEST_ASSERT (val_uint32_max_buffer[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32] == 0); + return 0; } /* main */