[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