Skip to content

Commit a79dc36

Browse files
committed
Fix parseInt when passing empty string.
Before allocating buffer for the string first we check that the length of it is greater then 0. If not then the result is a NaN. JerryScript-DCO-1.0-Signed-off-by: Peter Gal pgal.u-szeged@partner.samsung.com
1 parent c7a47c1 commit a79dc36

File tree

2 files changed

+119
-107
lines changed

2 files changed

+119
-107
lines changed

jerry-core/ecma/builtin-objects/ecma-builtin-global.cpp

Lines changed: 118 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -113,147 +113,158 @@ ecma_builtin_global_object_parse_int (ecma_value_t this_arg __attr_unused___, /*
113113
ecma_string_t *number_str_p = ecma_get_string_from_value (string_var);
114114
lit_utf8_size_t str_size = ecma_string_get_size (number_str_p);
115115

116-
MEM_DEFINE_LOCAL_ARRAY (utf8_string_buff, str_size, lit_utf8_byte_t);
117-
118-
ssize_t bytes_copied = ecma_string_to_utf8_string (number_str_p,
119-
utf8_string_buff,
120-
(ssize_t) str_size);
121-
JERRY_ASSERT (bytes_copied >= 0);
122-
utf8_string_buff[str_size] = LIT_BYTE_NULL;
123-
124-
/* 2. Remove leading whitespace. */
125-
ecma_length_t start = str_size;
126-
ecma_length_t end = str_size;
127-
for (ecma_length_t i = 0; i < end; i++)
116+
if (str_size > 0)
128117
{
129-
if (!lit_char_is_white_space (utf8_string_buff[i])
130-
&& !lit_char_is_line_terminator (utf8_string_buff[i]))
118+
MEM_DEFINE_LOCAL_ARRAY (utf8_string_buff, str_size, lit_utf8_byte_t);
119+
120+
ssize_t bytes_copied = ecma_string_to_utf8_string (number_str_p,
121+
utf8_string_buff,
122+
(ssize_t) str_size);
123+
JERRY_ASSERT (bytes_copied >= 0);
124+
utf8_string_buff[str_size] = LIT_BYTE_NULL;
125+
126+
/* 2. Remove leading whitespace. */
127+
ecma_length_t start = str_size;
128+
ecma_length_t end = str_size;
129+
for (ecma_length_t i = 0; i < end; i++)
131130
{
132-
start = i;
133-
break;
131+
if (!lit_char_is_white_space (utf8_string_buff[i])
132+
&& !lit_char_is_line_terminator (utf8_string_buff[i]))
133+
{
134+
start = i;
135+
break;
136+
}
134137
}
135-
}
136-
137-
/* 3. */
138-
int sign = 1;
139138

140-
/* 4. */
141-
if (utf8_string_buff[start] == '-')
142-
{
143-
sign = -1;
144-
}
139+
/* 3. */
140+
int sign = 1;
145141

146-
/* 5. */
147-
if (utf8_string_buff[start] == '-' || utf8_string_buff[start] == '+')
148-
{
149-
start++;
150-
}
151-
152-
/* 6. */
153-
ECMA_OP_TO_NUMBER_TRY_CATCH (radix_num, radix, ret_value);
154-
int32_t rad = ecma_number_to_int32 (radix_num);
155-
156-
/* 7.*/
157-
bool strip_prefix = true;
158-
159-
/* 8. */
160-
if (rad != 0)
161-
{
162-
/* 8.a */
163-
if (rad < 2 || rad > 36)
142+
/* 4. */
143+
if (utf8_string_buff[start] == LIT_CHAR_MINUS)
164144
{
165-
ecma_number_t *ret_num_p = ecma_alloc_number ();
166-
*ret_num_p = ecma_number_make_nan ();
167-
ret_value = ecma_make_normal_completion_value (ecma_make_number_value (ret_num_p));
145+
sign = -1;
168146
}
169-
/* 8.b */
170-
else if (rad != 16)
147+
148+
/* 5. */
149+
if (utf8_string_buff[start] == LIT_CHAR_MINUS || utf8_string_buff[start] == LIT_CHAR_PLUS)
171150
{
172-
strip_prefix = false;
151+
start++;
173152
}
174-
}
175-
/* 9. */
176-
else
177-
{
178-
rad = 10;
179-
}
180153

181-
if (ecma_is_completion_value_empty (ret_value))
182-
{
183-
/* 10. */
184-
if (strip_prefix)
185-
{
186-
if (end - start >= 2
187-
&& utf8_string_buff[start] == '0'
188-
&& (utf8_string_buff[start + 1] == 'x' || utf8_string_buff[start + 1] == 'X'))
189-
{
190-
start += 2;
154+
/* 6. */
155+
ECMA_OP_TO_NUMBER_TRY_CATCH (radix_num, radix, ret_value);
156+
int32_t rad = ecma_number_to_int32 (radix_num);
191157

192-
rad = 16;
193-
}
194-
}
158+
/* 7.*/
159+
bool strip_prefix = true;
195160

196-
/* 11. Check if characters are in [0, Radix - 1]. We also convert them to number values in the process. */
197-
for (lit_utf8_size_t i = start; i < end; i++)
161+
/* 8. */
162+
if (rad != 0)
198163
{
199-
if ((utf8_string_buff[i]) >= 'a' && utf8_string_buff[i] <= 'z')
164+
/* 8.a */
165+
if (rad < 2 || rad > 36)
200166
{
201-
utf8_string_buff[i] = (lit_utf8_byte_t) (utf8_string_buff[i] - 'a' + 10);
167+
ecma_number_t *ret_num_p = ecma_alloc_number ();
168+
*ret_num_p = ecma_number_make_nan ();
169+
ret_value = ecma_make_normal_completion_value (ecma_make_number_value (ret_num_p));
202170
}
203-
else if (utf8_string_buff[i] >= 'A' && utf8_string_buff[i] <= 'Z')
171+
/* 8.b */
172+
else if (rad != 16)
204173
{
205-
utf8_string_buff[i] = (lit_utf8_byte_t) (utf8_string_buff[i] - 'A' + 10);
174+
strip_prefix = false;
206175
}
207-
else if (lit_char_is_decimal_digit (utf8_string_buff[i]))
176+
}
177+
/* 9. */
178+
else
179+
{
180+
rad = 10;
181+
}
182+
183+
if (ecma_is_completion_value_empty (ret_value))
184+
{
185+
/* 10. */
186+
if (strip_prefix)
208187
{
209-
utf8_string_buff[i] = (lit_utf8_byte_t) (utf8_string_buff[i] - '0');
188+
if (end - start >= 2
189+
&& utf8_string_buff[start] == LIT_CHAR_0
190+
&& (utf8_string_buff[start + 1] == LIT_CHAR_LOWERCASE_X
191+
|| utf8_string_buff[start + 1] == LIT_CHAR_UPPERCASE_X))
192+
{
193+
start += 2;
194+
195+
rad = 16;
196+
}
210197
}
211-
else
198+
199+
/* 11. Check if characters are in [0, Radix - 1]. We also convert them to number values in the process. */
200+
for (lit_utf8_size_t i = start; i < end; i++)
212201
{
213-
/* Not a valid number char, set value to radix so it fails to pass as a valid character. */
214-
utf8_string_buff[i] = (lit_utf8_byte_t) rad;
202+
if ((utf8_string_buff[i]) >= LIT_CHAR_LOWERCASE_A && utf8_string_buff[i] <= LIT_CHAR_LOWERCASE_Z)
203+
{
204+
utf8_string_buff[i] = (lit_utf8_byte_t) (utf8_string_buff[i] - LIT_CHAR_LOWERCASE_A + 10);
205+
}
206+
else if (utf8_string_buff[i] >= LIT_CHAR_UPPERCASE_A && utf8_string_buff[i] <= LIT_CHAR_UPPERCASE_Z)
207+
{
208+
utf8_string_buff[i] = (lit_utf8_byte_t) (utf8_string_buff[i] - LIT_CHAR_UPPERCASE_A + 10);
209+
}
210+
else if (lit_char_is_decimal_digit (utf8_string_buff[i]))
211+
{
212+
utf8_string_buff[i] = (lit_utf8_byte_t) (utf8_string_buff[i] - LIT_CHAR_0);
213+
}
214+
else
215+
{
216+
/* Not a valid number char, set value to radix so it fails to pass as a valid character. */
217+
utf8_string_buff[i] = (lit_utf8_byte_t) rad;
218+
}
219+
220+
if (!(utf8_string_buff[i] < rad))
221+
{
222+
end = i;
223+
break;
224+
}
215225
}
216226

217-
if (!(utf8_string_buff[i] < rad))
227+
/* 12. */
228+
if (end - start == 0)
218229
{
219-
end = i;
220-
break;
230+
ecma_number_t *ret_num_p = ecma_alloc_number ();
231+
*ret_num_p = ecma_number_make_nan ();
232+
ret_value = ecma_make_normal_completion_value (ecma_make_number_value (ret_num_p));
221233
}
222234
}
223235

224-
/* 12. */
225-
if (end - start == 0)
236+
if (ecma_is_completion_value_empty (ret_value))
226237
{
227-
ecma_number_t *ret_num_p = ecma_alloc_number ();
228-
*ret_num_p = ecma_number_make_nan ();
229-
ret_value = ecma_make_normal_completion_value (ecma_make_number_value (ret_num_p));
230-
}
231-
}
238+
ecma_number_t *value_p = ecma_alloc_number ();
239+
*value_p = 0;
240+
ecma_number_t multiplier = 1.0f;
232241

233-
if (ecma_is_completion_value_empty (ret_value))
234-
{
235-
ecma_number_t *value_p = ecma_alloc_number ();
236-
*value_p = 0;
237-
ecma_number_t multiplier = 1.0f;
242+
/* 13. and 14. */
243+
for (int32_t i = (int32_t) end - 1; i >= (int32_t) start; i--)
244+
{
245+
*value_p += (ecma_number_t) utf8_string_buff[i] * multiplier;
246+
multiplier *= (ecma_number_t) rad;
247+
}
238248

239-
/* 13. and 14. */
240-
for (int32_t i = (int32_t) end - 1; i >= (int32_t) start; i--)
241-
{
242-
*value_p += (ecma_number_t) utf8_string_buff[i] * multiplier;
243-
multiplier *= (ecma_number_t) rad;
244-
}
249+
/* 15. */
250+
if (sign < 0)
251+
{
252+
*value_p *= (ecma_number_t) sign;
253+
}
245254

246-
/* 15. */
247-
if (sign < 0)
248-
{
249-
*value_p *= (ecma_number_t) sign;
255+
ret_value = ecma_make_normal_completion_value (ecma_make_number_value (value_p));
250256
}
251257

252-
ret_value = ecma_make_normal_completion_value (ecma_make_number_value (value_p));
258+
ECMA_OP_TO_NUMBER_FINALIZE (radix_num);
259+
MEM_FINALIZE_LOCAL_ARRAY (utf8_string_buff);
260+
}
261+
else
262+
{
263+
ecma_number_t *ret_num_p = ecma_alloc_number ();
264+
*ret_num_p = ecma_number_make_nan ();
265+
ret_value = ecma_make_normal_completion_value (ecma_make_number_value (ret_num_p));
253266
}
254267

255-
ECMA_OP_TO_NUMBER_FINALIZE (radix_num);
256-
MEM_FINALIZE_LOCAL_ARRAY (utf8_string_buff);
257268
ECMA_FINALIZE (string_var);
258269
return ret_value;
259270
} /* ecma_builtin_global_object_parse_int */

tests/jerry/global-parseint.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ assert(parseInt("ABC", 16) === 2748);
2727
assert(parseInt("12A3") === 12);
2828
assert(parseInt("12.34") === 12);
2929
assert(isNaN(parseInt("AB")));
30+
assert(isNaN(parseInt("")));
3031

3132
var bool = true;
3233
var obj = new Object();

0 commit comments

Comments
 (0)