Skip to content

Commit 71a02ec

Browse files
committed
[GR-23468] DelegatingInput/OutputStream should not malform higher code points.
PullRequest: js/1495
2 parents b42b0a5 + 25afae9 commit 71a02ec

File tree

3 files changed

+60
-5
lines changed

3 files changed

+60
-5
lines changed

graal-js/src/com.oracle.truffle.js.scriptengine.test/src/com/oracle/truffle/js/scriptengine/test/TestEngine.java

+26
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@
4747
import java.io.File;
4848
import java.io.FileWriter;
4949
import java.io.IOException;
50+
import java.io.StringReader;
51+
import java.io.StringWriter;
5052

5153
import javax.script.Bindings;
5254
import javax.script.Compilable;
@@ -57,6 +59,8 @@
5759
import javax.script.ScriptEngineManager;
5860
import javax.script.ScriptException;
5961

62+
import org.graalvm.polyglot.Context;
63+
import org.graalvm.polyglot.Engine;
6064
import org.graalvm.polyglot.Source;
6165
import org.junit.Ignore;
6266
import org.junit.Rule;
@@ -232,4 +236,26 @@ public void moduleWithDependency() throws IOException, ScriptException {
232236
assertSame(42, ((Number) result).intValue());
233237
}
234238

239+
@Test
240+
public void unicodeOutput() throws ScriptException {
241+
String text = "Tu\u010d\u0148\u00e1\u010d\u010d\u00ed \ud83d\udca9!";
242+
ScriptEngine engine = getEngine();
243+
StringWriter output = new StringWriter();
244+
engine.getContext().setWriter(output);
245+
engine.eval("print('" + text + "');");
246+
assertEquals(text + '\n', output.toString());
247+
}
248+
249+
@Test
250+
public void unicodeInput() throws ScriptException {
251+
String text = "Tu\u010d\u0148\u00e1\u010d\u010d\u00ed \ud83d\udca9!";
252+
ScriptEngine engine = GraalJSScriptEngine.create(
253+
Engine.newBuilder().build(),
254+
Context.newBuilder("js").allowExperimentalOptions(true).option("js.shell", "true"));
255+
StringReader input = new StringReader(text);
256+
engine.getContext().setReader(input);
257+
Object result = engine.eval("readline()");
258+
assertEquals(text, result);
259+
}
260+
235261
}

graal-js/src/com.oracle.truffle.js.scriptengine/src/com/oracle/truffle/js/scriptengine/GraalJSScriptEngine.java

+34-2
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@
4848
import java.io.Writer;
4949
import java.lang.reflect.Method;
5050
import java.lang.reflect.Modifier;
51+
import java.nio.ByteBuffer;
52+
import java.nio.CharBuffer;
53+
import java.nio.charset.Charset;
54+
import java.nio.charset.CharsetDecoder;
55+
import java.nio.charset.CharsetEncoder;
5156
import java.util.Objects;
5257
import java.util.function.Predicate;
5358

@@ -567,11 +572,26 @@ private void checkSyntax(Source source) throws ScriptException {
567572
private static class DelegatingInputStream extends InputStream implements Proxy {
568573

569574
private Reader reader;
575+
private CharsetEncoder encoder = Charset.defaultCharset().newEncoder();
576+
private CharBuffer charBuffer = CharBuffer.allocate(2);
577+
private ByteBuffer byteBuffer = (ByteBuffer) ByteBuffer.allocate((int) encoder.maxBytesPerChar() * 2).flip();
570578

571579
@Override
572580
public int read() throws IOException {
573581
if (reader != null) {
574-
return reader.read();
582+
while (!byteBuffer.hasRemaining()) {
583+
int c = reader.read();
584+
if (c == -1) {
585+
return -1;
586+
}
587+
byteBuffer.clear();
588+
charBuffer.put((char) c);
589+
charBuffer.flip();
590+
encoder.encode(charBuffer, byteBuffer, false);
591+
charBuffer.compact();
592+
byteBuffer.flip();
593+
}
594+
return byteBuffer.get();
575595
}
576596
return 0;
577597
}
@@ -585,11 +605,23 @@ void setReader(Reader reader) {
585605
private static class DelegatingOutputStream extends OutputStream implements Proxy {
586606

587607
private Writer writer;
608+
private CharsetDecoder decoder = Charset.defaultCharset().newDecoder();
609+
private ByteBuffer byteBuffer = ByteBuffer.allocate((int) Charset.defaultCharset().newEncoder().maxBytesPerChar() * 2);
610+
private CharBuffer charBuffer = CharBuffer.allocate(byteBuffer.capacity() * (int) decoder.maxCharsPerByte());
588611

589612
@Override
590613
public void write(int b) throws IOException {
591614
if (writer != null) {
592-
writer.write(b);
615+
byteBuffer.put((byte) b);
616+
byteBuffer.flip();
617+
decoder.decode(byteBuffer, charBuffer, false);
618+
byteBuffer.compact();
619+
charBuffer.flip();
620+
while (charBuffer.hasRemaining()) {
621+
char c = charBuffer.get();
622+
writer.write(c);
623+
}
624+
charBuffer.clear();
593625
}
594626
}
595627

graal-js/test/testNashorn.json

-3
Original file line numberDiff line numberDiff line change
@@ -187,9 +187,6 @@
187187
"filePath" : "basic/JDK-8015267.js",
188188
"status" : "FAIL",
189189
"comment" : "Java interop migration"
190-
}, {
191-
"filePath" : "basic/JDK-8015345.js",
192-
"status" : "FAIL"
193190
}, {
194191
"filePath" : "basic/JDK-8015352.js",
195192
"runInIsolation" : true

0 commit comments

Comments
 (0)