8073868: Regex matching causes java.lang.ArrayIndexOutOfBoundsException: 64

Reviewed-by: attila, lagergren
This commit is contained in:
Hannes Wallnöfer 2015-03-25 17:43:55 +01:00
parent 268d8ef7a6
commit 9454c8c825
5 changed files with 47 additions and 140 deletions

View File

@ -145,9 +145,6 @@ final class ArrayCompiler extends Compiler {
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

View File

@ -183,7 +183,6 @@ class ByteCodeMachine extends StackMachine {
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 @@ class ByteCodeMachine extends StackMachine {
}
}
// 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;
}

View File

@ -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 @@ abstract class StackMachine extends Matcher implements StackType {
}
}
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) {

View File

@ -24,5 +24,4 @@ public interface TargetInfo {
final int ISNOT_EMPTY = 0;
final int IS_EMPTY = 1;
final int IS_EMPTY_MEM = 2;
final int IS_EMPTY_REC = 3;
}

View File

@ -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);