From: Dmitry Volyntsev Date: Thu, 23 Jun 2022 06:37:27 +0000 (-0700) Subject: Fixed unicode argument trimming in parseInt(). X-Git-Tag: 0.7.6~14 X-Git-Url: http://www.kaiwu.me/postgresql/commit/static/gitweb.js?a=commitdiff_plain;h=a571dcaeabddc110d99301b2c0a7473cacd32af4;p=njs.git Fixed unicode argument trimming in parseInt(). --- diff --git a/src/njs_number.c b/src/njs_number.c index 5aa09196..f1079616 100644 --- a/src/njs_number.c +++ b/src/njs_number.c @@ -1064,42 +1064,31 @@ njs_int_t njs_number_parse_int(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num; - int32_t radix; - njs_int_t ret; - njs_str_t string; - njs_bool_t minus, test_prefix; - njs_value_t *value; - const u_char *p, *end; + double num; + int32_t radix; + njs_int_t ret; + njs_bool_t minus, test_prefix; + njs_value_t *value; + const u_char *p, *end; + njs_string_prop_t string; num = NAN; - if (nargs < 2) { - goto done; - } + value = njs_arg(args, nargs, 1); - value = njs_argument(args, 1); - - if (!njs_is_string(value)) { - ret = njs_value_to_string(vm, value, value); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } + ret = njs_value_to_string(vm, value, value); + if (njs_slow_path(ret != NJS_OK)) { + return ret; } - njs_string_get(value, &string); - - end = string.start + string.length; + (void) njs_string_trim(value, &string, NJS_TRIM_START); - for (p = string.start; p < end; p++) { - if (*p != ' ') { - goto found; - } + if (string.size == 0) { + goto done; } - goto done; - -found: + p = string.start; + end = p + string.size; minus = 0; @@ -1156,21 +1145,17 @@ njs_int_t njs_number_parse_float(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - double num; - njs_int_t ret; + njs_int_t ret; + njs_value_t *value; - num = NAN; + value = njs_arg(args, nargs, 1); - if (nargs > 1) { - ret = njs_value_to_string(vm, &args[1], &args[1]); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - - num = njs_string_to_number(&args[1], 1); + ret = njs_value_to_string(vm, value, value); + if (njs_slow_path(ret != NJS_OK)) { + return ret; } - njs_set_number(&vm->retval, num); + njs_set_number(&vm->retval, njs_string_to_number(value, 1)); return NJS_OK; } diff --git a/src/njs_string.c b/src/njs_string.c index 3cee90ab..1ba45815 100644 --- a/src/njs_string.c +++ b/src/njs_string.c @@ -8,10 +8,6 @@ #include -#define NJS_TRIM_START 1 -#define NJS_TRIM_END 2 - - static u_char njs_basis64[] = { 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, @@ -2761,36 +2757,27 @@ njs_string_prototype_to_upper_case(njs_vm_t *vm, njs_value_t *args, } -static njs_int_t -njs_string_prototype_trim(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, - njs_index_t mode) +uint32_t +njs_string_trim(const njs_value_t *value, njs_string_prop_t *string, + unsigned mode) { - uint32_t u, trim, length; - njs_int_t ret; - njs_value_t *value; + uint32_t cp, trim; const u_char *p, *prev, *start, *end; - njs_string_prop_t string; njs_unicode_decode_t ctx; - value = njs_argument(args, 0); - ret = njs_string_object_validate(vm, value); - if (njs_slow_path(ret != NJS_OK)) { - return ret; - } - trim = 0; - njs_string_prop(&string, value); + njs_string_prop(string, value); - start = string.start; - end = string.start + string.size; + start = string->start; + end = string->start + string->size; - if (njs_is_byte_or_ascii_string(&string)) { + if (njs_is_byte_or_ascii_string(string)) { if (mode & NJS_TRIM_START) { for ( ;; ) { if (start == end) { - goto empty; + break; } if (njs_is_whitespace(*start)) { @@ -2806,7 +2793,7 @@ njs_string_prototype_trim(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, if (mode & NJS_TRIM_END) { for ( ;; ) { if (start == end) { - goto empty; + break; } end--; @@ -2829,13 +2816,13 @@ njs_string_prototype_trim(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, for ( ;; ) { if (start == end) { - goto empty; + break; } p = start; - u = njs_utf8_decode(&ctx, &start, end); + cp = njs_utf8_decode(&ctx, &start, end); - if (njs_utf8_is_whitespace(u)) { + if (njs_utf8_is_whitespace(cp)) { trim++; continue; } @@ -2852,14 +2839,14 @@ njs_string_prototype_trim(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, for ( ;; ) { if (start == prev) { - goto empty; + break; } prev = njs_utf8_prev(prev); p = prev; - u = njs_utf8_decode(&ctx, &p, end); + cp = njs_utf8_decode(&ctx, &p, end); - if (njs_utf8_is_whitespace(u)) { + if (njs_utf8_is_whitespace(cp)) { trim++; continue; } @@ -2870,22 +2857,52 @@ njs_string_prototype_trim(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } } - if (trim == 0) { - /* GC: retain. */ - vm->retval = *value; + if (start == end) { + string->length = 0; + string->size = 0; + return trim; + } - return NJS_OK; + string->start = (u_char *) start; + string->size = end - start; + + if (string->length != 0) { + string->length -= trim; } - length = (string.length != 0) ? string.length - trim : 0; + return trim; +} + + +static njs_int_t +njs_string_prototype_trim(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, + njs_index_t mode) +{ + uint32_t trim; + njs_int_t ret; + njs_value_t *value; + njs_string_prop_t string; + + value = njs_argument(args, 0); + ret = njs_string_object_validate(vm, value); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } - return njs_string_new(vm, &vm->retval, start, end - start, length); + trim = njs_string_trim(value, &string, mode); -empty: + if (trim == 0) { + njs_value_assign(&vm->retval, value); + return NJS_OK; + } - vm->retval = njs_string_empty; + if (string.size == 0) { + njs_value_assign(&vm->retval, &njs_string_empty); + return NJS_OK; + } - return NJS_OK; + return njs_string_new(vm, &vm->retval, string.start, string.size, + string.length); } @@ -3811,38 +3828,17 @@ njs_string_prototype_iterator_obj(njs_vm_t *vm, njs_value_t *args, double njs_string_to_number(const njs_value_t *value, njs_bool_t parse_float) { - double num; - size_t size; - uint32_t u; - njs_bool_t minus; - const u_char *p, *start, *end; - njs_unicode_decode_t ctx; + double num; + njs_bool_t minus; + const u_char *p, *start, *end; + njs_string_prop_t string; const size_t infinity = njs_length("Infinity"); - size = value->short_string.size; - - if (size != NJS_STRING_LONG) { - p = value->short_string.start; - - } else { - size = value->long_string.size; - p = value->long_string.data->start; - } - - end = p + size; + (void) njs_string_trim(value, &string, NJS_TRIM_START); - njs_utf8_decode_init(&ctx); - - while (p < end) { - start = p; - u = njs_utf8_decode(&ctx, &p, end); - - if (!njs_utf8_is_whitespace(u)) { - p = start; - break; - } - } + p = string.start; + end = p + string.size; if (p == end) { return parse_float ? NAN : 0.0; diff --git a/src/njs_string.h b/src/njs_string.h index 3dfe9269..a126d3c8 100644 --- a/src/njs_string.h +++ b/src/njs_string.h @@ -98,6 +98,12 @@ typedef enum { } njs_utf8_t; +typedef enum { + NJS_TRIM_START = 1, + NJS_TRIM_END = 2, +} njs_trim_t; + + njs_inline njs_bool_t njs_is_byte_string(njs_string_prop_t *string) { @@ -224,6 +230,8 @@ njs_int_t njs_string_decode_base64(njs_vm_t *vm, njs_value_t *value, njs_int_t njs_string_decode_base64url(njs_vm_t *vm, njs_value_t *value, const njs_str_t *src); void njs_string_truncate(njs_value_t *value, uint32_t size, uint32_t length); +uint32_t njs_string_trim(const njs_value_t *value, njs_string_prop_t *string, + unsigned mode); void njs_string_copy(njs_value_t *dst, njs_value_t *src); njs_int_t njs_string_validate(njs_vm_t *vm, njs_string_prop_t *string, njs_value_t *value); diff --git a/src/test/njs_unit_test.c b/src/test/njs_unit_test.c index e9bb4248..4b406ba8 100644 --- a/src/test/njs_unit_test.c +++ b/src/test/njs_unit_test.c @@ -16744,6 +16744,12 @@ static njs_unit_test_t njs_test[] = { njs_str("parseInt(' 123')"), njs_str("123") }, + { njs_str("parseInt('\\u0009123')"), + njs_str("123") }, + + { njs_str("parseInt('\\u200A123')"), + njs_str("123") }, + { njs_str("parseInt('1010', 2)"), njs_str("10") },