8173807: JShell: control characters should be escaped in String values
Reviewed-by: jlahoda
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/DirectExecutionControl.java Mon Feb 06 09:00:02 2017 -0800
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/DirectExecutionControl.java Mon Feb 06 09:25:31 2017 -0800
@@ -28,6 +28,7 @@
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.util.stream.IntStream;
import jdk.jshell.spi.ExecutionControl;
import jdk.jshell.spi.SPIResolutionException;
@@ -41,6 +42,23 @@
*/
public class DirectExecutionControl implements ExecutionControl {
+ private static final String[] charRep;
+
+ static {
+ charRep = new String[256];
+ for (int i = 0; i < charRep.length; ++i) {
+ charRep[i] = Character.isISOControl(i)
+ ? String.format("\\%03o", i)
+ : "" + (char) i;
+ }
+ charRep['\b'] = "\\b";
+ charRep['\t'] = "\\t";
+ charRep['\n'] = "\\n";
+ charRep['\f'] = "\\f";
+ charRep['\r'] = "\\r";
+ charRep['\\'] = "\\\\";
+ }
+
private final LoaderDelegate loaderDelegate;
/**
@@ -192,9 +210,26 @@
if (value == null) {
return "null";
} else if (value instanceof String) {
- return "\"" + (String) value + "\"";
+ return "\"" + ((String) value).codePoints()
+ .flatMap(cp ->
+ (cp == '"')
+ ? "\\\"".codePoints()
+ : (cp < 256)
+ ? charRep[cp].codePoints()
+ : IntStream.of(cp))
+ .collect(
+ StringBuilder::new,
+ StringBuilder::appendCodePoint,
+ StringBuilder::append)
+ .toString() + "\"";
} else if (value instanceof Character) {
- return "'" + value + "'";
+ char cp = (char) (Character) value;
+ return "'" + (
+ (cp == '\'')
+ ? "\\\'"
+ : (cp < 256)
+ ? charRep[cp]
+ : String.valueOf(cp)) + "'";
} else if (value.getClass().isArray()) {
int dims = 0;
Class<?> t = value.getClass();
--- a/langtools/test/jdk/jshell/SimpleRegressionTest.java Mon Feb 06 09:00:02 2017 -0800
+++ b/langtools/test/jdk/jshell/SimpleRegressionTest.java Mon Feb 06 09:25:31 2017 -0800
@@ -22,7 +22,7 @@
*/
/*
- * @test 8130450 8158906 8154374 8166400 8171892 8173848
+ * @test 8130450 8158906 8154374 8166400 8171892 8173807 8173848
* @summary simple regression test
* @build KullaTesting TestingInputStream
* @run testng SimpleRegressionTest
@@ -191,4 +191,36 @@
assertEval("new boolean[2][1][3]",
"boolean[2][][] { boolean[1][] { boolean[3] { false, false, false } }, boolean[1][] { boolean[3] { false, false, false } } }");
}
+
+ public void testStringRepresentation() {
+ assertEval("\"A!\\rB!\"",
+ "\"A!\\rB!\"");
+ assertEval("\"a\\bB\\tc\\nd\\fe\\rf\\\"g'\\\\h\"",
+ "\"a\\bB\\tc\\nd\\fe\\rf\\\"g'\\\\h\"");
+ assertEval("\"\\141\\10B\\11c\\nd\\fe\\15f\\42g\\'\\134h\"",
+ "\"a\\bB\\tc\\nd\\fe\\rf\\\"g'\\\\h\"");
+ assertEval("\"1234567890!@#$%^&*()-_=+qwertQWERT,./<>?;:[]{}\"",
+ "\"1234567890!@#$%^&*()-_=+qwertQWERT,./<>?;:[]{}\"");
+ assertEval("\"AA\\1\\7\\35\\25\"",
+ "\"AA\\001\\007\\035\\025\"");
+ assertEval("\"\"",
+ "\"\"");
+ assertEval("(String)null",
+ "null");
+ }
+
+ public void testCharRepresentation() {
+ for (String s : new String[]{"'A'", "'Z'", "'0'", "'9'",
+ "'a'", "'z'", "'*'", "'%'",
+ "'\\b'", "'\\t'", "'\\n'", "'\\f'", "'\\r'",
+ "'\"'", "'\\\''", "'\\\\'", "'\\007'", "'\\034'",}) {
+ assertEval(s, s);
+ }
+ assertEval("'\\3'",
+ "'\\003'");
+ assertEval("'\\u001D'",
+ "'\\035'");
+ assertEval("\"a\\bb\\tc\\nd\\fe\\rf\\\"g'\\\\h\".charAt(1)",
+ "'\\b'");
+ }
}