[njs] Fixes in various String methods which return part of string.
Igor Sysoev
igor at sysoev.ru
Mon Oct 17 14:01:43 UTC 2016
details: http://hg.nginx.org/njs/rev/938d49b0f420
branches:
changeset: 202:938d49b0f420
user: Igor Sysoev <igor at sysoev.ru>
date: Mon Oct 17 16:42:31 2016 +0300
description:
Fixes in various String methods which return part of string.
diffstat:
njs/njs_array.c | 3 +
njs/njs_string.c | 164 ++++++++++++++++++++++++++--------------------
njs/njs_vm.c | 16 ++--
njs/test/njs_unit_test.c | 15 ++++
4 files changed, 118 insertions(+), 80 deletions(-)
diffs (296 lines):
diff -r c583e4985a7b -r 938d49b0f420 njs/njs_array.c
--- a/njs/njs_array.c Fri Oct 14 18:21:37 2016 +0300
+++ b/njs/njs_array.c Mon Oct 17 16:42:31 2016 +0300
@@ -409,6 +409,9 @@ njs_array_prototype_slice(njs_vm_t *vm,
start = 0;
length = 0;
}
+
+ } else {
+ length -= start;
}
}
}
diff -r c583e4985a7b -r 938d49b0f420 njs/njs_string.c
--- a/njs/njs_string.c Fri Oct 14 18:21:37 2016 +0300
+++ b/njs/njs_string.c Mon Oct 17 16:42:31 2016 +0300
@@ -886,21 +886,29 @@ njs_string_prototype_substring(njs_vm_t
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;
-
- if (length < 0) {
- length = -length;
- start = end;
- }
+ }
+
+ length = end - start;
+
+ 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
if (nargs > 1) {
start = args[1].data.u.number;
-
- if (start < 0) {
-
- start += length;
+ if (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 *v
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 *
}
}
- end = length;
-
- if (nargs > 2) {
- end = args[2].data.u.number;
-
- if (end < 0) {
- end += length;
- }
- }
-
- length = end - start;
-
- if (length < 0) {
+ if (start >= length) {
start = 0;
length = 0;
+
+ } else {
+ end = length;
+
+ if (nargs > 2) {
+ end = args[2].data.u.number;
+
+ if (end < 0) {
+ end += length;
+ }
+ }
+
+ if (length >= end) {
+ length = end - start;
+
+ if (length < 0) {
+ start = 0;
+ length = 0;
+ }
+
+ } else {
+ length -= start;
+ }
}
}
@@ -1038,51 +1073,36 @@ njs_string_slice(njs_vm_t *vm, njs_value
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;
-
- if (length > 0 && slice->start < slice->string_length) {
-
- start = string->start;
+ start = string->start;
+
+ if (string->size == slice->string_length) {
+ /* Byte or ASCII string. */
+ start += slice->start;
+ size = slice->length;
+
+ } else {
+ /* UTF-8 string. */
end = start + string->size;
-
- if (string->size == slice->string_length) {
- /* Byte or ASCII string. */
- start += slice->start;
-
- excess = (start + length) - end;
- if (excess > 0) {
- length -= excess;
- }
-
- size = length;
-
- if (string->length == 0) {
- length = 0;
- }
-
- } else {
- /* UTF-8 string. */
- start = njs_string_offset(start, end, slice->start);
-
- /* 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;
- }
-
- if (nxt_fast_path(size != 0)) {
- return njs_string_new(vm, &vm->retval, start, size, length);
- }
+ start = njs_string_offset(start, end, slice->start);
+
+ /* 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;
+ }
+
+ if (nxt_fast_path(size != 0)) {
+ return njs_string_new(vm, &vm->retval, start, size, length);
}
vm->retval = njs_string_empty;
diff -r c583e4985a7b -r 938d49b0f420 njs/njs_vm.c
--- a/njs/njs_vm.c Fri Oct 14 18:21:37 2016 +0300
+++ b/njs/njs_vm.c Mon Oct 17 16:42:31 2016 +0300
@@ -559,14 +559,14 @@ njs_vmcode_property_get(njs_vm_t *vm, nj
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 -r c583e4985a7b -r 938d49b0f420 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c Fri Oct 14 18:21:37 2016 +0300
+++ b/njs/test/njs_unit_test.c Mon Oct 17 16:42:31 2016 +0300
@@ -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") },
More information about the nginx-devel
mailing list