diff --git a/jerry-core/api/jerry-snapshot.c b/jerry-core/api/jerry-snapshot.c index 30d912eae2..caa6529f26 100644 --- a/jerry-core/api/jerry-snapshot.c +++ b/jerry-core/api/jerry-snapshot.c @@ -1499,11 +1499,13 @@ 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 6ee8f59bf2..8661f0d8b7 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -1501,6 +1501,12 @@ typedef double ecma_number_t; */ #define ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32 10 +/** + * Maximum number of characters in string representation of ecma-uint32 plus one. + * That is the '\0' terminator + */ +#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 819282d826..c2e8b05a4f 100644 --- a/jerry-core/ecma/base/ecma-helpers-conversion.c +++ b/jerry-core/ecma/base/ecma-helpers-conversion.c @@ -618,7 +618,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 { @@ -631,12 +632,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 */ @@ -824,7 +826,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); } @@ -891,7 +893,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 9aa9a49784..ddac6c1d4e 100644 --- a/jerry-core/ecma/base/ecma-helpers-string.c +++ b/jerry-core/ecma/base/ecma-helpers-string.c @@ -746,7 +746,8 @@ ecma_append_chars_to_string (ecma_string_t *string1_p, /**< base ecma-string */ return ecma_get_magic_string (magic_string_id); } - if ((cesu8_string1_flags & ECMA_STRING_FLAG_IS_UINT32) && new_size < ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32) + if ((cesu8_string1_flags & ECMA_STRING_FLAG_IS_UINT32) + && new_size < ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32_WITH_ZERO_TERMINATED) { memcpy (cesu8_string1_uint32_buffer + cesu8_string1.size, cesu8_string2_p, cesu8_string2_size); @@ -1061,8 +1062,9 @@ 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); @@ -1170,7 +1172,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; @@ -1268,11 +1270,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; @@ -1319,11 +1321,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; @@ -1689,8 +1691,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)) { @@ -1702,7 +1704,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; } } @@ -1718,7 +1720,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; } } @@ -1733,7 +1735,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; } } @@ -1749,7 +1751,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; } } @@ -2034,7 +2036,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)) { @@ -2059,7 +2061,9 @@ 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]; } @@ -2105,7 +2109,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 2816deaec9..065770d85e 100644 --- a/jerry-core/ecma/base/ecma-helpers.h +++ b/jerry-core/ecma/base/ecma-helpers.h @@ -113,7 +113,7 @@ typedef enum utf8_str) /**< [out] lit_utf8_string_t to get */ \ lit_utf8_string_t utf8_str; \ uint8_t utf8_str##_flags = ECMA_STRING_FLAG_EMPTY; \ - lit_utf8_byte_t utf8_str##_uint32_buffer[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32]; \ + lit_utf8_byte_t utf8_str##_uint32_buffer[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32_WITH_ZERO_TERMINATED]; \ (void) ecma_string_get_chars (ecma_str_ptr, &utf8_str, utf8_str##_uint32_buffer, &utf8_str##_flags); \ JERRY_ASSERT (!(utf8_str##_flags & ECMA_STRING_FLAG_MUST_BE_FREED)); @@ -125,13 +125,13 @@ typedef enum * The string length name is `utf8_str##_length` * */ -#define ECMA_STRING_TO_UTF8_STRING_AND_LENGTH(ecma_str_ptr, /**< ecma string pointer */ \ - utf8_str) /**< [out] lit_utf8_string_t to get */ \ - lit_utf8_string_t utf8_str; \ - uint8_t utf8_str##_flags = ECMA_STRING_FLAG_IS_ASCII; \ - lit_utf8_byte_t utf8_str##_uint32_buffer[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32]; \ - lit_utf8_size_t utf8_str##_length = \ - ecma_string_get_chars (ecma_str_ptr, &utf8_str, utf8_str##_uint32_buffer, &utf8_str##_flags); \ +#define ECMA_STRING_TO_UTF8_STRING_AND_LENGTH(ecma_str_ptr, /**< ecma string pointer */ \ + utf8_str) /**< [out] lit_utf8_string_t to get */ \ + lit_utf8_string_t utf8_str; \ + uint8_t utf8_str##_flags = ECMA_STRING_FLAG_IS_ASCII; \ + lit_utf8_byte_t utf8_str##_uint32_buffer[ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32_WITH_ZERO_TERMINATED]; \ + lit_utf8_size_t utf8_str##_length = \ + ecma_string_get_chars (ecma_str_ptr, &utf8_str, utf8_str##_uint32_buffer, &utf8_str##_flags); \ JERRY_ASSERT (!(utf8_str##_flags & ECMA_STRING_FLAG_MUST_BE_FREED)); #ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY @@ -519,6 +519,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 e5a3c8fe08..6b5ac7bd7f 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/jerry-core/parser/js/js-parser.c b/jerry-core/parser/js/js-parser.c index dad4db6c18..afae768fcd 100644 --- a/jerry-core/parser/js/js-parser.c +++ b/jerry-core/parser/js/js-parser.c @@ -2418,12 +2418,12 @@ parser_parse_source (void *source_p, /**< source code */ if (context.global_status_flags & ECMA_PARSE_INTERNAL_FREE_SOURCE) { - jmem_heap_free_block ((void *) context.source.ptr, context.source.size); + jmem_heap_free_block ((void *) context.source.ptr, context.source.size + 1); } if (context.global_status_flags & ECMA_PARSE_INTERNAL_FREE_ARG_LIST) { - jmem_heap_free_block ((void *) context.arguments.ptr, context.arguments.size); + jmem_heap_free_block ((void *) context.arguments.ptr, context.arguments.size + 1); } if (compiled_code_p != NULL) diff --git a/tests/unit-core/test-number-to-string.c b/tests/unit-core/test-number-to-string.c index ed5fce2261..b53d089113 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 */