提交 9791d2fc 编写于 作者: H hannesw

8016542: String.prototype.replace called with function argument should not replace $ patterns

Reviewed-by: lagergren, jlaskey
上级 dd971fca
...@@ -641,26 +641,19 @@ public final class NativeRegExp extends ScriptObject { ...@@ -641,26 +641,19 @@ public final class NativeRegExp extends ScriptObject {
return string; return string;
} }
/*
* $$ -> $
* $& -> the matched substring
* $` -> the portion of string that preceeds matched substring
* $' -> the portion of string that follows the matched substring
* $n -> the nth capture, where n is [1-9] and $n is NOT followed by a decimal digit
* $nn -> the nnth capture, where nn is a two digit decimal number [01-99].
*/
String replace = replacement;
if (!regexp.isGlobal()) { if (!regexp.isGlobal()) {
if (!matcher.search(0)) { if (!matcher.search(0)) {
return string; return string;
} }
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
sb.append(string, 0, matcher.start());
if (function != null) { if (function != null) {
replace = callReplaceValue(function, matcher, string); sb.append(callReplaceValue(function, matcher, string));
} else {
appendReplacement(matcher, string, replacement, sb);
} }
appendReplacement(matcher, string, replace, sb, 0);
sb.append(string, matcher.end(), string.length()); sb.append(string, matcher.end(), string.length());
return sb.toString(); return sb.toString();
} }
...@@ -676,12 +669,13 @@ public final class NativeRegExp extends ScriptObject { ...@@ -676,12 +669,13 @@ public final class NativeRegExp extends ScriptObject {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
do { do {
sb.append(string, thisIndex, matcher.start());
if (function != null) { if (function != null) {
replace = callReplaceValue(function, matcher, string); sb.append(callReplaceValue(function, matcher, string));
} else {
appendReplacement(matcher, string, replacement, sb);
} }
appendReplacement(matcher, string, replace, sb, thisIndex);
// ECMA 15.5.4.10 String.prototype.match(regexp) // ECMA 15.5.4.10 String.prototype.match(regexp)
thisIndex = matcher.end(); thisIndex = matcher.end();
if (thisIndex == previousLastIndex) { if (thisIndex == previousLastIndex) {
...@@ -697,10 +691,19 @@ public final class NativeRegExp extends ScriptObject { ...@@ -697,10 +691,19 @@ public final class NativeRegExp extends ScriptObject {
return sb.toString(); return sb.toString();
} }
private void appendReplacement(final RegExpMatcher matcher, final String text, final String replacement, final StringBuilder sb, final int lastAppendPosition) { private void appendReplacement(final RegExpMatcher matcher, final String text, final String replacement, final StringBuilder sb) {
// Process substitution string to replace group references with groups /*
* Process substitution patterns:
*
* $$ -> $
* $& -> the matched substring
* $` -> the portion of string that preceeds matched substring
* $' -> the portion of string that follows the matched substring
* $n -> the nth capture, where n is [1-9] and $n is NOT followed by a decimal digit
* $nn -> the nnth capture, where nn is a two digit decimal number [01-99].
*/
int cursor = 0; int cursor = 0;
final StringBuilder result = new StringBuilder();
Object[] groups = null; Object[] groups = null;
while (cursor < replacement.length()) { while (cursor < replacement.length()) {
...@@ -732,37 +735,33 @@ public final class NativeRegExp extends ScriptObject { ...@@ -732,37 +735,33 @@ public final class NativeRegExp extends ScriptObject {
} }
// Append group if matched. // Append group if matched.
if (groups[refNum] != UNDEFINED) { if (groups[refNum] != UNDEFINED) {
result.append((String) groups[refNum]); sb.append((String) groups[refNum]);
} }
} else { // $0. ignore. } else { // $0. ignore.
assert refNum == 0; assert refNum == 0;
result.append("$0"); sb.append("$0");
} }
} else if (nextChar == '$') { } else if (nextChar == '$') {
result.append('$'); sb.append('$');
cursor++; cursor++;
} else if (nextChar == '&') { } else if (nextChar == '&') {
result.append(matcher.group()); sb.append(matcher.group());
cursor++; cursor++;
} else if (nextChar == '`') { } else if (nextChar == '`') {
result.append(text.substring(0, matcher.start())); sb.append(text, 0, matcher.start());
cursor++; cursor++;
} else if (nextChar == '\'') { } else if (nextChar == '\'') {
result.append(text.substring(matcher.end())); sb.append(text, matcher.end(), text.length());
cursor++; cursor++;
} else { } else {
// unknown substitution or $n with n>m. skip. // unknown substitution or $n with n>m. skip.
result.append('$'); sb.append('$');
} }
} else { } else {
result.append(nextChar); sb.append(nextChar);
cursor++; cursor++;
} }
} }
// Append the intervening text
sb.append(text, lastAppendPosition, matcher.start());
// Append the match substitution
sb.append(result);
} }
private String callReplaceValue(final ScriptFunction function, final RegExpMatcher matcher, final String string) { private String callReplaceValue(final ScriptFunction function, final RegExpMatcher matcher, final String string) {
......
/*
* Copyright (c) 2010, 2013, 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-8016542: String.prototype.replace called with function argument should not replace $ patterns
*
* @test
* @run
*/
print("abc".replace("a", "$&"));
print("abc".replace("b", "$&"));
print("abc".replace("c", "$&"));
print("abc".replace("a", function(){return "$&"}));
print("abc".replace("b", function(){return "$&"}));
print("abc".replace("c", function(){return "$&"}));
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册