mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-20 11:50:25 +00:00
8341495: JShell crashes with java.util.MissingFormatArgumentException
Reviewed-by: jlahoda
This commit is contained in:
parent
ba158edd81
commit
bcebb0c53c
@ -72,6 +72,7 @@ import java.util.Scanner;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.prefs.Preferences;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
@ -805,46 +806,46 @@ public class JShellTool implements MessageHandler {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add normal prefixing/postfixing to embedded newlines in a string,
|
||||
* Add normal prefixing/postfixing to embedded newlines in a format string,
|
||||
* bracketing with normal prefix/postfix
|
||||
*
|
||||
* @param s the string to prefix
|
||||
* @return the pre/post-fixed and bracketed string
|
||||
* @param format the format string to prefix/postfix
|
||||
* @return the pre/post-fixed and bracketed format string
|
||||
*/
|
||||
String prefix(String s) {
|
||||
return prefix(s, feedback.getPre(), feedback.getPost());
|
||||
String prefix(String format) {
|
||||
return prefix(format, feedback.getPre(), feedback.getPost());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add error prefixing/postfixing to embedded newlines in a string,
|
||||
* Add error prefixing/postfixing to embedded newlines in a format string,
|
||||
* bracketing with error prefix/postfix
|
||||
*
|
||||
* @param s the string to prefix
|
||||
* @return the pre/post-fixed and bracketed string
|
||||
* @param format the format string to prefix/postfix
|
||||
* @return the pre/post-fixed and bracketed format string
|
||||
*/
|
||||
String prefixError(String s) {
|
||||
return prefix(s, feedback.getErrorPre(), feedback.getErrorPost());
|
||||
String prefixError(String format) {
|
||||
return prefix(format, feedback.getErrorPre(), feedback.getErrorPost());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add prefixing/postfixing to embedded newlines in a string,
|
||||
* Add prefixing/postfixing to embedded newlines in a format string,
|
||||
* bracketing with prefix/postfix. No prefixing when non-interactive.
|
||||
* Result is expected to be the format for a printf.
|
||||
* Both input and result strings are expected to be the format for a printf.
|
||||
*
|
||||
* @param s the string to prefix
|
||||
* @param pre the string to prepend to each line
|
||||
* @param post the string to append to each line (replacing newline)
|
||||
* @return the pre/post-fixed and bracketed string
|
||||
* @param format the format string to prefix
|
||||
* @param pre the string to prepend to each line (printf safe)
|
||||
* @param post the string to append to each line (replacing newline; printf safe)
|
||||
* @return the pre/post-fixed and bracketed format string
|
||||
*/
|
||||
String prefix(String s, String pre, String post) {
|
||||
if (s == null) {
|
||||
String prefix(String format, String pre, String post) {
|
||||
if (format == null) {
|
||||
return "";
|
||||
}
|
||||
if (!interactiveModeBegun) {
|
||||
// messages expect to be new-line terminated (even when not prefixed)
|
||||
return s + "%n";
|
||||
return format + "%n";
|
||||
}
|
||||
String pp = s.replaceAll("\\R", post + pre);
|
||||
String pp = format.replaceAll("\\R", post + pre);
|
||||
if (pp.endsWith(post + pre)) {
|
||||
// prevent an extra prefix char and blank line when the string
|
||||
// already terminates with newline
|
||||
@ -859,7 +860,7 @@ public class JShellTool implements MessageHandler {
|
||||
* @param key the resource key
|
||||
*/
|
||||
void hardrb(String key) {
|
||||
hard(getResourceString(key));
|
||||
hard(escape(getResourceString(key)));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -882,7 +883,7 @@ public class JShellTool implements MessageHandler {
|
||||
*/
|
||||
@Override
|
||||
public void hardmsg(String key, Object... args) {
|
||||
hard(messageFormat(key, args));
|
||||
hard(escape(messageFormat(key, args)));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -912,7 +913,7 @@ public class JShellTool implements MessageHandler {
|
||||
}
|
||||
|
||||
<T> void hardPairs(Stream<T> stream, Function<T, String> a, Function<T, String> b) {
|
||||
Map<String, String> a2b = stream.collect(toMap(a, b,
|
||||
Map<String, String> a2b = stream.collect(toMap(a, b.andThen(this::escape),
|
||||
(m1, m2) -> m1,
|
||||
LinkedHashMap::new));
|
||||
for (Entry<String, String> e : a2b.entrySet()) {
|
||||
@ -921,6 +922,13 @@ public class JShellTool implements MessageHandler {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape '%' signs in a plain string to make it a valid format string.
|
||||
*/
|
||||
String escape(Object s) {
|
||||
return s.toString().replace("%", "%%");
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim whitespace off end of string
|
||||
*
|
||||
@ -2332,7 +2340,7 @@ public class JShellTool implements MessageHandler {
|
||||
sb.append(startup.show(false));
|
||||
sb.append(startup.showDetail());
|
||||
}
|
||||
hard(sb.toString());
|
||||
hard(escape(sb));
|
||||
}
|
||||
|
||||
private void showIndent() {
|
||||
@ -3262,7 +3270,7 @@ public class JShellTool implements MessageHandler {
|
||||
sb.append(a);
|
||||
}
|
||||
if (sb.length() > 0) {
|
||||
hard(sb.toString());
|
||||
hard(escape(sb));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -3777,7 +3785,7 @@ public class JShellTool implements MessageHandler {
|
||||
case NONEXISTENT:
|
||||
default:
|
||||
// Should not occur
|
||||
error("Unexpected status: " + previousStatus.toString() + "=>" + status.toString());
|
||||
error("Unexpected status: %s=>%s", previousStatus, status);
|
||||
act = FormatAction.DROPPED;
|
||||
}
|
||||
return act;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2016, 2024, 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
|
||||
@ -1052,7 +1052,7 @@ Show the normal prompt and the continuation-prompts:\n\
|
||||
\n\
|
||||
Where <mode> is the name of a previously defined feedback mode.\n\
|
||||
Where <prompt> and <continuation-prompt> are quoted strings to be printed as input prompts.\n\
|
||||
Both may optionally contain '%%s' which will be substituted with the next snippet ID --\n\
|
||||
Both may optionally contain '%s' which will be substituted with the next snippet ID --\n\
|
||||
note that what is entered may not be assigned that ID, for example it may be an error or command.\n\
|
||||
The continuation-prompt is used on the second and subsequent lines of a multi-line snippet.\n\
|
||||
\n\
|
||||
|
||||
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2024, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8341495
|
||||
* @summary Test for crash caused by format specifier in startup script
|
||||
* @modules jdk.compiler/com.sun.tools.javac.api
|
||||
* jdk.compiler/com.sun.tools.javac.main
|
||||
* jdk.jshell/jdk.internal.jshell.tool
|
||||
* @library /tools/lib
|
||||
* @build toolbox.ToolBox
|
||||
* @build KullaTesting Compiler
|
||||
* @run testng StartupWithFormatSpecifierTest
|
||||
*/
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
@Test
|
||||
public class StartupWithFormatSpecifierTest extends ReplToolTesting {
|
||||
|
||||
public void testStartupWithFormatSpecifier() {
|
||||
Compiler compiler = new Compiler();
|
||||
String startupScript = "String.format(\"This is a %s.\", \"test\");";
|
||||
Path startupFile = compiler.getPath("StartupFileOption/startup.txt");
|
||||
compiler.writeToFile(startupFile, startupScript);
|
||||
test(new String[] { "--startup", startupFile.toString() },
|
||||
(a) -> assertCommandOutputContains(a, "/set start", startupScript)
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user