Skip to content

Commit f3081a0

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 6038173 commit f3081a0

File tree

2 files changed

+117
-106
lines changed

2 files changed

+117
-106
lines changed

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

Lines changed: 116 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -112,146 +112,156 @@ ecma_builtin_global_object_parse_int (ecma_value_t this_arg __attr_unused___, /*
112112
ecma_string_t *number_str_p = ecma_get_string_from_value (string_var);
113113
lit_utf8_size_t str_size = ecma_string_get_size (number_str_p);
114114

115-
MEM_DEFINE_LOCAL_ARRAY (utf8_string_buff, str_size, lit_utf8_byte_t);
116-
117-
ssize_t bytes_copied = ecma_string_to_utf8_string (number_str_p,
118-
utf8_string_buff,
119-
(ssize_t) str_size);
120-
JERRY_ASSERT (bytes_copied >= 0);
121-
utf8_string_buff[str_size] = LIT_BYTE_NULL;
122-
123-
/* 2. Remove leading whitespace. */
124-
ecma_length_t start = str_size;
125-
ecma_length_t end = str_size;
126-
for (ecma_length_t i = 0; i < end; i++)
115+
if (str_size > 0)
127116
{
128-
if (!(isspace (utf8_string_buff[i])))
117+
MEM_DEFINE_LOCAL_ARRAY (utf8_string_buff, str_size, lit_utf8_byte_t);
118+
119+
ssize_t bytes_copied = ecma_string_to_utf8_string (number_str_p,
120+
utf8_string_buff,
121+
(ssize_t) str_size);
122+
JERRY_ASSERT (bytes_copied >= 0);
123+
utf8_string_buff[str_size] = LIT_BYTE_NULL;
124+
125+
/* 2. Remove leading whitespace. */
126+
ecma_length_t start = str_size;
127+
ecma_length_t end = str_size;
128+
for (ecma_length_t i = 0; i < end; i++)
129129
{
130-
start = i;
131-
break;
130+
if (!(isspace (utf8_string_buff[i])))
131+
{
132+
start = i;
133+
break;
134+
}
132135
}
133-
}
134-
135-
/* 3. */
136-
int sign = 1;
137-
138-
/* 4. */
139-
if (utf8_string_buff[start] == '-')
140-
{
141-
sign = -1;
142-
}
143-
144-
/* 5. */
145-
if (utf8_string_buff[start] == '-' || utf8_string_buff[start] == '+')
146-
{
147-
start++;
148-
}
149-
150-
/* 6. */
151-
ECMA_OP_TO_NUMBER_TRY_CATCH (radix_num, radix, ret_value);
152-
int32_t rad = ecma_number_to_int32 (radix_num);
153136

154-
/* 7.*/
155-
bool strip_prefix = true;
137+
/* 3. */
138+
int sign = 1;
156139

157-
/* 8. */
158-
if (rad != 0)
159-
{
160-
/* 8.a */
161-
if (rad < 2 || rad > 36)
140+
/* 4. */
141+
if (utf8_string_buff[start] == '-')
162142
{
163-
ecma_number_t *ret_num_p = ecma_alloc_number ();
164-
*ret_num_p = ecma_number_make_nan ();
165-
ret_value = ecma_make_normal_completion_value (ecma_make_number_value (ret_num_p));
143+
sign = -1;
166144
}
167-
/* 8.b */
168-
else if (rad != 16)
145+
146+
/* 5. */
147+
if (utf8_string_buff[start] == '-' || utf8_string_buff[start] == '+')
169148
{
170-
strip_prefix = false;
149+
start++;
171150
}
172-
}
173-
/* 9. */
174-
else
175-
{
176-
rad = 10;
177-
}
178151

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

190-
rad = 16;
191-
}
192-
}
156+
/* 7.*/
157+
bool strip_prefix = true;
193158

194-
/* 11. Check if characters are in [0, Radix - 1]. We also convert them to number values in the process. */
195-
for (lit_utf8_size_t i = start; i < end; i++)
159+
/* 8. */
160+
if (rad != 0)
196161
{
197-
if ((utf8_string_buff[i]) >= 'a' && utf8_string_buff[i] <= 'z')
162+
/* 8.a */
163+
if (rad < 2 || rad > 36)
198164
{
199-
utf8_string_buff[i] = (lit_utf8_byte_t) (utf8_string_buff[i] - 'a' + 10);
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));
200168
}
201-
else if (utf8_string_buff[i] >= 'A' && utf8_string_buff[i] <= 'Z')
169+
/* 8.b */
170+
else if (rad != 16)
202171
{
203-
utf8_string_buff[i] = (lit_utf8_byte_t) (utf8_string_buff[i] - 'A' + 10);
172+
strip_prefix = false;
204173
}
205-
else if (isdigit (utf8_string_buff[i]))
174+
}
175+
/* 9. */
176+
else
177+
{
178+
rad = 10;
179+
}
180+
181+
if (ecma_is_completion_value_empty (ret_value))
182+
{
183+
/* 10. */
184+
if (strip_prefix)
206185
{
207-
utf8_string_buff[i] = (lit_utf8_byte_t) (utf8_string_buff[i] - '0');
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;
191+
192+
rad = 16;
193+
}
208194
}
209-
else
195+
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++)
210198
{
211-
/* Not a valid number char, set value to radix so it fails to pass as a valid character. */
212-
utf8_string_buff[i] = (lit_utf8_byte_t) rad;
199+
if ((utf8_string_buff[i]) >= 'a' && utf8_string_buff[i] <= 'z')
200+
{
201+
utf8_string_buff[i] = (lit_utf8_byte_t) (utf8_string_buff[i] - 'a' + 10);
202+
}
203+
else if (utf8_string_buff[i] >= 'A' && utf8_string_buff[i] <= 'Z')
204+
{
205+
utf8_string_buff[i] = (lit_utf8_byte_t) (utf8_string_buff[i] - 'A' + 10);
206+
}
207+
else if (isdigit (utf8_string_buff[i]))
208+
{
209+
utf8_string_buff[i] = (lit_utf8_byte_t) (utf8_string_buff[i] - '0');
210+
}
211+
else
212+
{
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;
215+
}
216+
217+
if (!(utf8_string_buff[i] < rad))
218+
{
219+
end = i;
220+
break;
221+
}
213222
}
214223

215-
if (!(utf8_string_buff[i] < rad))
224+
/* 12. */
225+
if (end - start == 0)
216226
{
217-
end = i;
218-
break;
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));
219230
}
220231
}
221232

222-
/* 12. */
223-
if (end - start == 0)
233+
if (ecma_is_completion_value_empty (ret_value))
224234
{
225-
ecma_number_t *ret_num_p = ecma_alloc_number ();
226-
*ret_num_p = ecma_number_make_nan ();
227-
ret_value = ecma_make_normal_completion_value (ecma_make_number_value (ret_num_p));
228-
}
229-
}
235+
ecma_number_t *value_p = ecma_alloc_number ();
236+
*value_p = 0;
237+
ecma_number_t multiplier = 1.0f;
230238

231-
if (ecma_is_completion_value_empty (ret_value))
232-
{
233-
ecma_number_t *value_p = ecma_alloc_number ();
234-
*value_p = 0;
235-
ecma_number_t multiplier = 1.0f;
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+
}
236245

237-
/* 13. and 14. */
238-
for (int32_t i = (int32_t) end - 1; i >= (int32_t) start; i--)
239-
{
240-
*value_p += (ecma_number_t) utf8_string_buff[i] * multiplier;
241-
multiplier *= (ecma_number_t) rad;
242-
}
246+
/* 15. */
247+
if (sign < 0)
248+
{
249+
*value_p *= (ecma_number_t) sign;
250+
}
243251

244-
/* 15. */
245-
if (sign < 0)
246-
{
247-
*value_p *= (ecma_number_t) sign;
252+
ret_value = ecma_make_normal_completion_value (ecma_make_number_value (value_p));
248253
}
249254

250-
ret_value = ecma_make_normal_completion_value (ecma_make_number_value (value_p));
255+
ECMA_OP_TO_NUMBER_FINALIZE (radix_num);
256+
MEM_FINALIZE_LOCAL_ARRAY (utf8_string_buff);
257+
}
258+
else
259+
{
260+
ecma_number_t *ret_num_p = ecma_alloc_number ();
261+
*ret_num_p = ecma_number_make_nan ();
262+
ret_value = ecma_make_normal_completion_value (ecma_make_number_value (ret_num_p));
251263
}
252264

253-
ECMA_OP_TO_NUMBER_FINALIZE (radix_num);
254-
MEM_FINALIZE_LOCAL_ARRAY (utf8_string_buff);
255265
ECMA_FINALIZE (string_var);
256266
return ret_value;
257267
} /* 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)