From: Igor Sysoev Date: Mon, 17 Oct 2016 13:42:31 +0000 (+0300) Subject: Fixes in various String methods which return part of string. X-Git-Tag: 0.1.4~12 X-Git-Url: http://git.kaiwu.me/postgresql/log/contrib/postgres_fdw/static/gitweb.js?a=commitdiff_plain;h=ee4187d88929646defc1b0f7a20925c75b3d8647;p=njs.git Fixes in various String methods which return part of string. --- diff --git a/njs/njs_array.c b/njs/njs_array.c index 39bdfa61..da040125 100644 --- a/njs/njs_array.c +++ b/njs/njs_array.c @@ -409,6 +409,9 @@ njs_array_prototype_slice(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, start = 0; length = 0; } + + } else { + length -= start; } } } diff --git a/njs/njs_string.c b/njs/njs_string.c index 6b4bffd2..cd449aea 100644 --- a/njs/njs_string.c +++ b/njs/njs_string.c @@ -886,21 +886,29 @@ njs_string_prototype_substring(njs_vm_t *vm, njs_value_t *args, if (start < 0) { start = 0; + + } else if (start > length) { + start = length; } + end = length; + if (nargs > 2) { end = args[2].data.u.number; if (end < 0) { end = 0; + + } else if (end >= length) { + end = length; } + } - length = end - start; + length = end - start; - if (length < 0) { - length = -length; - start = end; - } + if (length < 0) { + length = -length; + start = end; } } @@ -920,7 +928,7 @@ static njs_ret_t njs_string_prototype_substr(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused) { - ssize_t start, length; + ssize_t start, length, n; njs_slice_prop_t slice; njs_string_prop_t string; @@ -931,17 +939,32 @@ njs_string_prototype_substr(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, if (nargs > 1) { start = args[1].data.u.number; + if (start < length) { - if (start < 0) { - - start += length; if (start < 0) { - start = 0; + start += length; + + if (start < 0) { + start = 0; + } } - } - if (nargs > 2) { - length = args[2].data.u.number; + length -= start; + + if (nargs > 2) { + n = args[2].data.u.number; + + if (n < 0) { + length = 0; + + } else if (n < length) { + length = n; + } + } + + } else { + start = 0; + length = 0; } } @@ -968,7 +991,8 @@ njs_string_prototype_char_at(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, if (nargs > 1) { start = args[1].data.u.number; - if (start < 0) { + if (start < 0 || start >= (ssize_t) slice.string_length) { + start = 0; length = 0; } } @@ -1010,21 +1034,32 @@ njs_string_slice_args(njs_slice_prop_t *slice, njs_value_t *args, } } - end = length; + if (start >= length) { + start = 0; + length = 0; - if (nargs > 2) { - end = args[2].data.u.number; + } else { + end = length; - if (end < 0) { - end += length; + if (nargs > 2) { + end = args[2].data.u.number; + + if (end < 0) { + end += length; + } } - } - length = end - start; + if (length >= end) { + length = end - start; - if (length < 0) { - start = 0; - length = 0; + if (length < 0) { + start = 0; + length = 0; + } + + } else { + length -= start; + } } } @@ -1038,51 +1073,36 @@ njs_string_slice(njs_vm_t *vm, njs_value_t *dst, const njs_string_prop_t *string, njs_slice_prop_t *slice) { size_t size, n, length; - ssize_t excess; const u_char *p, *start, *end; length = slice->length; + start = string->start; - if (length > 0 && slice->start < slice->string_length) { + if (string->size == slice->string_length) { + /* Byte or ASCII string. */ + start += slice->start; + size = slice->length; - start = string->start; + } else { + /* UTF-8 string. */ end = start + string->size; + start = njs_string_offset(start, end, slice->start); - if (string->size == slice->string_length) { - /* Byte or ASCII string. */ - start += slice->start; - - excess = (start + length) - end; - if (excess > 0) { - length -= excess; - } - - size = length; + /* Evaluate size of the slice in bytes and ajdust length. */ + p = start; + n = length; - if (string->length == 0) { - length = 0; - } - - } else { - /* UTF-8 string. */ - start = njs_string_offset(start, end, slice->start); + do { + p = nxt_utf8_next(p, end); + n--; + } while (n != 0 && p < end); - /* Evaluate size of the slice in bytes and ajdust length. */ - p = start; - n = length; - - do { - p = nxt_utf8_next(p, end); - n--; - } while (n != 0 && p < end); - - size = p - start; - length -= n; - } + size = p - start; + length -= n; + } - if (nxt_fast_path(size != 0)) { - return njs_string_new(vm, &vm->retval, start, size, length); - } + if (nxt_fast_path(size != 0)) { + return njs_string_new(vm, &vm->retval, start, size, length); } vm->retval = njs_string_empty; diff --git a/njs/njs_vm.c b/njs/njs_vm.c index 18051974..3443966b 100644 --- a/njs/njs_vm.c +++ b/njs/njs_vm.c @@ -559,14 +559,14 @@ njs_vmcode_property_get(njs_vm_t *vm, njs_value_t *object, slice.start = index; slice.length = 1; slice.string_length = njs_string_prop(&string, object); - /* - * A single codepoint string fits in vm->retval - * so the function cannot fail. - */ - (void) njs_string_slice(vm, &vm->retval, &string, &slice); - if (nxt_fast_path(vm->retval.data.truth != 0)) { - /* Non-empty string. */ + if (slice.start < slice.string_length) { + /* + * A single codepoint string fits in vm->retval + * so the function cannot fail. + */ + (void) njs_string_slice(vm, &vm->retval, &string, &slice); + return sizeof(njs_vmcode_prop_get_t); } } diff --git a/njs/test/njs_unit_test.c b/njs/test/njs_unit_test.c index fba0788f..5101264d 100644 --- a/njs/test/njs_unit_test.c +++ b/njs/test/njs_unit_test.c @@ -2857,6 +2857,12 @@ static njs_unit_test_t njs_test[] = { nxt_string("'abcdefgh'.slice(3)"), nxt_string("defgh") }, + { nxt_string("'abcde'.slice(50)"), + nxt_string("") }, + + { nxt_string("'abcde'.slice(1, 50)"), + nxt_string("bcde") }, + { nxt_string("'abcdefgh'.slice(3, -2)"), nxt_string("def") }, @@ -2866,6 +2872,15 @@ static njs_unit_test_t njs_test[] = { nxt_string("'abcdefgh'.slice(100, 120)"), nxt_string("") }, + { nxt_string("String.prototype.substring(1, 5)"), + nxt_string("") }, + + { nxt_string("String.prototype.slice(1, 5)"), + nxt_string("") }, + + { nxt_string("String.prototype.toBytes(1, 5)"), + nxt_string("") }, + { nxt_string("'abc'.charAt(1 + 1)"), nxt_string("c") },