Skip to content

Commit

Permalink
Fixes ecma_uint32_to_utf8_string that fill \0 at the end of string
Browse files Browse the repository at this point in the history
Closes: jerryscript-project#5194

JerryScript-DCO-1.0-Signed-off-by: Yonggang Luo [email protected]
  • Loading branch information
lygstate committed Dec 17, 2024
1 parent 5390294 commit 287772e
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 35 deletions.
8 changes: 5 additions & 3 deletions jerry-core/api/jerry-snapshot.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
6 changes: 6 additions & 0 deletions jerry-core/ecma/base/ecma-globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down
10 changes: 6 additions & 4 deletions jerry-core/ecma/base/ecma-helpers-conversion.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -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 */
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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 */
Expand Down
38 changes: 21 additions & 17 deletions jerry-core/ecma/base/ecma-helpers-string.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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))
{
Expand All @@ -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;
}
}
Expand All @@ -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;
}
}
Expand All @@ -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;
}
}
Expand All @@ -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;
}
}
Expand Down Expand Up @@ -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))
{
Expand All @@ -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];
}
Expand Down Expand Up @@ -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];
}
Expand Down
17 changes: 9 additions & 8 deletions jerry-core/ecma/base/ecma-helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -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));

Expand All @@ -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
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
4 changes: 2 additions & 2 deletions jerry-core/parser/js/js-parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
12 changes: 12 additions & 0 deletions tests/unit-core/test-number-to-string.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

0 comments on commit 287772e

Please sign in to comment.