From b11007055d061c5755dbc7184871d449e5c54e9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20B=C3=A1tyai?= Date: Wed, 22 Jul 2015 15:06:50 +0200 Subject: [PATCH] Fix buffer size calculation in Number.prototype.toString() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JerryScript-DCO-1.0-Signed-off-by: Dániel Bátyai dbatyai.u-szeged@partner.samsung.com --- .../ecma-builtin-number-prototype.cpp | 51 ++++++++++--------- tests/jerry/number-prototype-to-string.js | 2 + 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-number-prototype.cpp b/jerry-core/ecma/builtin-objects/ecma-builtin-number-prototype.cpp index ec4aaad04..5a0730244 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-number-prototype.cpp +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-number-prototype.cpp @@ -133,6 +133,7 @@ ecma_builtin_number_prototype_object_to_string (ecma_value_t this_arg, /**< this int32_t num_digits; int32_t exponent; bool is_negative = false; + bool should_round = false; if (ecma_number_is_negative (this_arg_number)) { @@ -148,11 +149,17 @@ ecma_builtin_number_prototype_object_to_string (ecma_value_t this_arg, /**< this /* Calculate the scale of the number in the specified radix. */ int scale = (int) -floor ((log (10) / log (radix)) * exponent); + if (scale < 0) + { + is_scale_negative = true; + scale = -scale; + } + int buff_size; if (is_scale_negative) { - buff_size = (int) floor ((log (this_arg_number) / log (10))) + 1; + buff_size = (int) floor (log (this_arg_number) / log (radix)) + 1; } else { @@ -164,12 +171,6 @@ ecma_builtin_number_prototype_object_to_string (ecma_value_t this_arg, /**< this buff_size++; } - if (scale < 0) - { - is_scale_negative = true; - scale = -scale; - } - /* Normalize the number, so that it is as close to 0 exponent as possible. */ for (int i = 0; i < scale; i++) { @@ -186,6 +187,13 @@ ecma_builtin_number_prototype_object_to_string (ecma_value_t this_arg, /**< this uint64_t whole = (uint64_t) this_arg_number; ecma_number_t fraction = this_arg_number - (ecma_number_t) whole; + if (!ecma_number_is_zero (fraction) && is_scale_negative) + { + /* Add one extra digit for rounding. */ + buff_size++; + should_round = true; + } + MEM_DEFINE_LOCAL_ARRAY (buff, buff_size, lit_utf8_byte_t); int buff_index = 0; @@ -207,29 +215,26 @@ ecma_builtin_number_prototype_object_to_string (ecma_value_t this_arg, /**< this buff[buff_index - i - 1] = swap; } - bool should_round = false; + int required_digits = buff_size; + if (is_negative) + { + required_digits--; + } + + if (!is_scale_negative) + { + /* Leave space for leading zeros / radix point. */ + required_digits -= scale + 1; + } + /* Calculate digits for fractional part. */ - for (int iter_count = 0; - iter_count < ECMA_NUMBER_FRACTION_WIDTH && (fraction != 0 || is_scale_negative); - iter_count++) + while (buff_index < required_digits && (fraction != 0 || is_scale_negative)) { fraction *= (ecma_number_t) radix; lit_utf8_byte_t digit = (lit_utf8_byte_t) floor (fraction); buff[buff_index++] = digit; fraction -= (ecma_number_t) floor (fraction); - - if (iter_count == scale && is_scale_negative) - { - /* - * When scale is negative, that means the original number did not have a fractional part, - * but by normalizing it, we introduced one. In this case, when the iteration count reaches - * the scale, we already have the number, but it may be incorrect, so we calculate - * one extra digit that we round off just to make sure. - */ - should_round = true; - break; - } } if (should_round) diff --git a/tests/jerry/number-prototype-to-string.js b/tests/jerry/number-prototype-to-string.js index e229de798..a1e669b39 100644 --- a/tests/jerry/number-prototype-to-string.js +++ b/tests/jerry/number-prototype-to-string.js @@ -41,6 +41,8 @@ assert((-0.03125).toString(2) === "-0.00001"); assert((-0.03125).toString(16) === "-0.08"); assert((-0.0001).toString(4) === "-0.000000122031232023223013010030231") assert((-0).toString(16) === "0"); +assert((1e+73).toString(35) === "2nx1mg1l0w4ujlpt449c5qfrkkmtpgpsfsc2prlaqtnjbli2") +assert((-1e+73).toString(35) === "-2nx1mg1l0w4ujlpt449c5qfrkkmtpgpsfsc2prlaqtnjbli2") assert((123400).toString(2) === "11110001000001000"); assert((123400).toString(3) === "20021021101");