8073868: Regex matching causes java.lang.ArrayIndexOutOfBoundsException: 64
authorhannesw
Wed, 25 Mar 2015 17:43:55 +0100
changeset 29754 52fcf799b386
parent 29627 03fe257ba844
child 29755 a7940ef16738
8073868: Regex matching causes java.lang.ArrayIndexOutOfBoundsException: 64 Reviewed-by: attila, lagergren
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/ArrayCompiler.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/ByteCodeMachine.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/StackMachine.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/constants/TargetInfo.java
nashorn/test/script/basic/JDK-8073868.js
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/ArrayCompiler.java	Wed Mar 25 14:41:47 2015 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/ArrayCompiler.java	Wed Mar 25 17:43:55 2015 +0100
@@ -145,9 +145,6 @@
             case TargetInfo.IS_EMPTY_MEM:
                 addOpcode(OPCode.NULL_CHECK_END_MEMST);
                 break;
-            case TargetInfo.IS_EMPTY_REC:
-                addOpcode(OPCode.NULL_CHECK_END_MEMST_PUSH);
-                break;
             default:
                 break;
             } // switch
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/ByteCodeMachine.java	Wed Mar 25 14:41:47 2015 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/ByteCodeMachine.java	Wed Mar 25 17:43:55 2015 +0100
@@ -183,7 +183,6 @@
                 case OPCode.NULL_CHECK_START:           opNullCheckStart();        continue;
                 case OPCode.NULL_CHECK_END:             opNullCheckEnd();          continue;
                 case OPCode.NULL_CHECK_END_MEMST:       opNullCheckEndMemST();     continue;
-                case OPCode.NULL_CHECK_END_MEMST_PUSH:  opNullCheckEndMemSTPush(); continue;
 
                 case OPCode.JUMP:                       opJump();                  continue;
                 case OPCode.PUSH:                       opPush();                  continue;
@@ -1025,29 +1024,6 @@
         }
     }
 
-    // USE_SUBEXP_CALL
-    private void opNullCheckEndMemSTPush() {
-        final int mem = code[ip++];   /* mem: null check id */
-
-        int isNull;
-        if (Config.USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT) {
-            isNull = nullCheckMemStRec(mem, s);
-        } else {
-            isNull = nullCheckRec(mem, s);
-        }
-
-        if (isNull != 0) {
-            if (Config.DEBUG_MATCH) {
-                Config.log.println("NULL_CHECK_END_MEMST_PUSH: skip  id:" + mem + ", s:" + s);
-            }
-
-            if (isNull == -1) {opFail(); return;}
-            nullCheckFound();
-        } else {
-            pushNullCheckEnd(mem);
-        }
-    }
-
     private void opJump() {
         ip += code[ip] + 1;
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/StackMachine.java	Wed Mar 25 14:41:47 2015 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/StackMachine.java	Wed Mar 25 17:43:55 2015 +0100
@@ -19,7 +19,6 @@
  */
 package jdk.nashorn.internal.runtime.regexp.joni;
 
-import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsAt;
 import java.lang.ref.WeakReference;
 import jdk.nashorn.internal.runtime.regexp.joni.constants.StackPopLevel;
 import jdk.nashorn.internal.runtime.regexp.joni.constants.StackType;
@@ -369,118 +368,9 @@
         }
     }
 
-    protected final int nullCheckRec(final int id, final int s) {
-        int level = 0;
-        int k = stk;
-        while (true) {
-            k--;
-            final StackEntry e = stack[k];
-
-            if (e.type == NULL_CHECK_START) {
-                if (e.getNullCheckNum() == id) {
-                    if (level == 0) {
-                        return e.getNullCheckPStr() == s ? 1 : 0;
-                    }
-                    level--;
-                }
-            } else if (e.type == NULL_CHECK_END) {
-                level++;
-            }
-        }
-    }
-
     protected final int nullCheckMemSt(final int id, final int s) {
-        int k = stk;
-        int isNull;
-        while (true) {
-            k--;
-            StackEntry e = stack[k];
-
-            if (e.type == NULL_CHECK_START) {
-                if (e.getNullCheckNum() == id) {
-                    if (e.getNullCheckPStr() != s) {
-                        isNull = 0;
-                        break;
-                    }
-                    int endp;
-                    isNull = 1;
-                    while (k < stk) {
-                        if (e.type == MEM_START) {
-                            if (e.getMemEnd() == INVALID_INDEX) {
-                                isNull = 0;
-                                break;
-                            }
-                            if (bsAt(regex.btMemEnd, e.getMemNum())) {
-                                endp = stack[e.getMemEnd()].getMemPStr();
-                            } else {
-                                endp = e.getMemEnd();
-                            }
-                            if (stack[e.getMemStart()].getMemPStr() != endp) {
-                                isNull = 0;
-                                break;
-                            } else if (endp != s) {
-                                isNull = -1; /* empty, but position changed */
-                            }
-                        }
-                        k++;
-                        e = stack[k]; // !!
-                    }
-                    break;
-                }
-            }
-        }
-        return isNull;
-    }
-
-    protected final int nullCheckMemStRec(final int id, final int s) {
-        int level = 0;
-        int k = stk;
-        int isNull;
-        while (true) {
-            k--;
-            StackEntry e = stack[k];
-
-            if (e.type == NULL_CHECK_START) {
-                if (e.getNullCheckNum() == id) {
-                    if (level == 0) {
-                        if (e.getNullCheckPStr() != s) {
-                            isNull = 0;
-                            break;
-                        }
-                        int endp;
-                        isNull = 1;
-                        while (k < stk) {
-                            if (e.type == MEM_START) {
-                                if (e.getMemEnd() == INVALID_INDEX) {
-                                    isNull = 0;
-                                    break;
-                                }
-                                if (bsAt(regex.btMemEnd, e.getMemNum())) {
-                                    endp = stack[e.getMemEnd()].getMemPStr();
-                                } else {
-                                    endp = e.getMemEnd();
-                                }
-                                if (stack[e.getMemStart()].getMemPStr() != endp) {
-                                    isNull = 0;
-                                    break;
-                                } else if (endp != s) {
-                                    isNull = -1; /* empty, but position changed */
-                                }
-                            }
-                            k++;
-                            e = stack[k];
-                        }
-                        break;
-                    }
-                    level--;
-                }
-            } else if (e.type == NULL_CHECK_END) {
-                if (e.getNullCheckNum() == id) {
-                    level++;
-                }
-            }
-        }
-        return isNull;
+        // Return -1 here to cause operation to fail
+        return -nullCheck(id, s);
     }
 
     protected final int getRepeat(final int id) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/constants/TargetInfo.java	Wed Mar 25 14:41:47 2015 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/constants/TargetInfo.java	Wed Mar 25 17:43:55 2015 +0100
@@ -24,5 +24,4 @@
     final int ISNOT_EMPTY   = 0;
     final int IS_EMPTY      = 1;
     final int IS_EMPTY_MEM  = 2;
-    final int IS_EMPTY_REC  = 3;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8073868.js	Wed Mar 25 17:43:55 2015 +0100
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8073868: Regex matching causes java.lang.ArrayIndexOutOfBoundsException: 64
+ *
+ * @test
+ * @run
+ */
+
+function test(input) {
+    var comma = input.indexOf(",");
+    Assert.assertEquals(/([^\s]+),(.*)+/.exec(input)[0], input.trimLeft());
+    Assert.assertEquals(/([^\s]+),(.*)+/.exec(input)[1], input.substring(0, comma).trimLeft());
+    Assert.assertEquals(/([^\s]+),(.*)+/.exec(input)[2], input.substring(comma + 1));
+    Assert.assertEquals(/(.*)+/.exec(input)[0], input);
+    Assert.assertEquals(/(.*)+/.exec(input)[1], input);
+}
+
+test(" xxxx,         xxx xxxxxx xxxxxxxxx xxxxxxx, xxxx xxxxx xxxxx ");
+test(" xxxx, xxx xxxxxx xxxxxxxxx xxxxxxx, xxxx xxxxx xxxxx ");
+test("x,         xxxxxxxxxx xxxxxxxxx xxxxxxx, xxxx xxxxx xxxxx ");
+
+Assert.assertEquals(/(?:\1a|())*/.exec("a")[0], "a");
+Assert.assertEquals(/(?:\1a|())*/.exec("a")[1], undefined);