details: https://hg.nginx.org/njs/rev/0b82f1c9268c branches: changeset: 1075:0b82f1c9268c user: Valentin Bartenev <vb...@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_ */ _______________________________________________ nginx-devel mailing list nginx-devel@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel