[njs] Fixed String.fromCharCode() for code points > 65535 and NaN.
Valentin Bartenev
vbart at nginx.com
Sat Jul 27 13:13:01 UTC 2019
details: https://hg.nginx.org/njs/rev/0b82f1c9268c
branches:
changeset: 1075:0b82f1c9268c
user: Valentin Bartenev <vbart at nginx.com>
date: Sat Jul 27 16:12:26 2019 +0300
description:
Fixed String.fromCharCode() for code points > 65535 and NaN.
According to the specification the code units must be truncated to uint16.
diffstat:
njs/njs_number.h | 7 +++++++
njs/njs_string.c | 26 +++++---------------------
njs/test/njs_interactive_test.c | 4 ++--
njs/test/njs_unit_test.c | 28 +++++++++++++++-------------
nxt/nxt_utf8.h | 4 ++++
5 files changed, 33 insertions(+), 36 deletions(-)
diffs (172 lines):
diff -r ab9fc6079788 -r 0b82f1c9268c njs/njs_number.h
--- a/njs/njs_number.h Fri Jul 26 07:24:36 2019 +0300
+++ b/njs/njs_number.h Sat Jul 27 16:12:26 2019 +0300
@@ -86,6 +86,13 @@ njs_number_to_uint32(double num)
}
+nxt_inline uint16_t
+njs_number_to_uint16(double num)
+{
+ return (uint16_t) njs_number_to_int64(num);
+}
+
+
nxt_inline uint32_t
njs_number_to_length(double num)
{
diff -r ab9fc6079788 -r 0b82f1c9268c njs/njs_string.c
--- a/njs/njs_string.c Fri Jul 26 07:24:36 2019 +0300
+++ b/njs/njs_string.c Sat Jul 27 16:12:26 2019 +0300
@@ -1694,9 +1694,8 @@ njs_string_from_char_code(njs_vm_t *vm,
nxt_uint_t nargs, njs_index_t unused)
{
u_char *p;
- double num;
size_t size;
- int32_t code;
+ uint16_t code;
njs_ret_t ret;
nxt_uint_t i;
@@ -1712,18 +1711,8 @@ njs_string_from_char_code(njs_vm_t *vm,
size = 0;
for (i = 1; i < nargs; i++) {
- num = njs_number(&args[i]);
- if (isnan(num)) {
- goto range_error;
- }
-
- code = num;
-
- if (code != num || code < 0 || code >= 0x110000) {
- goto range_error;
- }
-
- size += nxt_utf8_size(code);
+ code = njs_number_to_uint16(njs_number(&args[i]));
+ size += nxt_utf8_size_uint16(code);
}
p = njs_string_alloc(vm, &vm->retval, size, nargs - 1);
@@ -1732,16 +1721,11 @@ njs_string_from_char_code(njs_vm_t *vm,
}
for (i = 1; i < nargs; i++) {
- p = nxt_utf8_encode(p, njs_number(&args[i]));
+ code = njs_number_to_uint16(njs_number(&args[i]));
+ p = nxt_utf8_encode(p, code);
}
return NXT_OK;
-
-range_error:
-
- njs_range_error(vm, NULL);
-
- return NXT_ERROR;
}
diff -r ab9fc6079788 -r 0b82f1c9268c njs/test/njs_interactive_test.c
--- a/njs/test/njs_interactive_test.c Fri Jul 26 07:24:36 2019 +0300
+++ b/njs/test/njs_interactive_test.c Sat Jul 27 16:12:26 2019 +0300
@@ -149,9 +149,9 @@ static njs_interactive_test_t njs_test[
" at f (:1)\n"
" at main (native)\n") },
- { nxt_string("String.fromCharCode(3.14)" ENTER),
+ { nxt_string("''.repeat(-1)" ENTER),
nxt_string("RangeError\n"
- " at String.fromCharCode (native)\n"
+ " at String.prototype.repeat (native)\n"
" at main (native)\n") },
{ nxt_string("Math.log({}.a.a)" ENTER),
diff -r ab9fc6079788 -r 0b82f1c9268c njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c Fri Jul 26 07:24:36 2019 +0300
+++ b/njs/test/njs_unit_test.c Sat Jul 27 16:12:26 2019 +0300
@@ -5345,11 +5345,17 @@ static njs_unit_test_t njs_test[] =
" .length; a"),
nxt_string("5") },
- { nxt_string("String.fromCharCode('_')"),
- nxt_string("RangeError") },
-
- { nxt_string("String.fromCharCode(3.14)"),
- nxt_string("RangeError") },
+ { nxt_string("String.fromCharCode('_').charCodeAt(0)"),
+ nxt_string("0") },
+
+ { nxt_string("String.fromCharCode(65.14)"),
+ nxt_string("A") },
+
+ { nxt_string("String.fromCharCode(65.14 + 65536)"),
+ nxt_string("A") },
+
+ { nxt_string("String.fromCharCode(2**53 + 10)"),
+ nxt_string("\n") },
{ nxt_string("String.fromCharCode(65, 90)"),
nxt_string("AZ") },
@@ -5357,17 +5363,15 @@ static njs_unit_test_t njs_test[] =
{ nxt_string("String.fromCharCode(945, 946, 947)"),
nxt_string("αβγ") },
-#if (!NXT_HAVE_MEMORY_SANITIZER) /* very long test under MSAN */
{ nxt_string("(function() {"
" var n;"
- " for (n = 0; n <= 1114111; n++) {"
+ " for (n = 0; n <= 65536; n++) {"
" if (String.fromCharCode(n).charCodeAt(0) !== n)"
" return n;"
" }"
" return -1"
"})()"),
- nxt_string("-1") },
-#endif
+ nxt_string("65536") },
{ nxt_string("var a = 'abcdef'; function f(a) {"
"return a.slice(a.indexOf('cd')) } f(a)"),
@@ -5567,9 +5571,8 @@ static njs_unit_test_t njs_test[] =
nxt_string("10") },
#if 0 /* FIXME */
-#if (!NXT_HAVE_MEMORY_SANITIZER) /* very long test under MSAN */
{ nxt_string("var a = [], code;"
- "for (code = 0; code <= 1114111; code++) {"
+ "for (code = 0; code < 65536; code++) {"
" var s = String.fromCharCode(code);"
" var n = s.toUpperCase();"
" if (s != n && s != n.toLowerCase())"
@@ -5578,7 +5581,7 @@ static njs_unit_test_t njs_test[] =
nxt_string("181,305,383,453,456,459,498,837,962,976,977,981,982,1008,1009,1013,7296,7297,7298,7299,7300,7301,7302,7303,7304,7835,8126") },
{ nxt_string("var a = [], code;"
- "for (code = 0; code <= 1114111; code++) {"
+ "for (code = 0; code < 65536; code++) {"
" var s = String.fromCharCode(code);"
" var n = s.toLowerCase();"
" if (s != n && s != n.toUpperCase())"
@@ -5586,7 +5589,6 @@ static njs_unit_test_t njs_test[] =
"} a"),
nxt_string("304,453,456,459,498,1012,7838,8486,8490,8491") },
#endif
-#endif
{ nxt_string("'abc'.trim()"),
nxt_string("abc") },
diff -r ab9fc6079788 -r 0b82f1c9268c nxt/nxt_utf8.h
--- a/nxt/nxt_utf8.h Fri Jul 26 07:24:36 2019 +0300
+++ b/nxt/nxt_utf8.h Sat Jul 27 16:12:26 2019 +0300
@@ -118,4 +118,8 @@ nxt_utf8_copy(u_char *dst, const u_char
((u < 0x80) ? 1 : ((u < 0x0800) ? 2 : ((u < 0x10000) ? 3 : 4)))
+#define nxt_utf8_size_uint16(u) \
+ ((u < 0x80) ? 1 : ((u < 0x0800) ? 2 : 3))
+
+
#endif /* _NXT_UTF8_H_INCLUDED_ */
More information about the nginx-devel
mailing list