Skip to content

Commit 7a28dfc

Browse files
committed
[JVM] Die instead of silently dropping data
There is more to do with regard to decoding of invalid input, but this patch already helps a bit.
1 parent ddb5d2d commit 7a28dfc

File tree

1 file changed

+47
-7
lines changed

1 file changed

+47
-7
lines changed

src/vm/jvm/runtime/org/perl6/nqp/sixmodel/reprs/DecoderInstance.java

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,18 @@
22

33
import java.nio.ByteBuffer;
44
import java.nio.CharBuffer;
5+
import java.nio.charset.CharacterCodingException;
56
import java.nio.charset.Charset;
67
import java.nio.charset.CharsetDecoder;
8+
import java.nio.charset.CoderResult;
9+
import java.nio.charset.MalformedInputException;
10+
import java.nio.charset.StandardCharsets;
711
import java.text.Normalizer;
812
import java.util.ArrayList;
913
import java.util.List;
1014
import org.perl6.nqp.runtime.Buffers;
1115
import org.perl6.nqp.runtime.ExceptionHandling;
16+
import org.perl6.nqp.runtime.Ops;
1217
import org.perl6.nqp.runtime.ThreadContext;
1318
import org.perl6.nqp.sixmodel.SixModelObject;
1419
import org.perl6.nqp.sixmodel.StorageSpec;
@@ -63,8 +68,17 @@ public synchronized String takeChars(ThreadContext tc, long chars, boolean eof)
6368

6469
CharBuffer target = CharBuffer.allocate((int)chars + 1);
6570
eatDecodedChars(target, (int)(chars + 1));
66-
if (target.position() != chars + 1)
67-
eatUndecodedBytes(target, false);
71+
if (target.position() != chars + 1) {
72+
try {
73+
eatUndecodedBytes(target, false);
74+
}
75+
catch (MalformedInputException e) {
76+
Ops.die_s("Will not decode invalid " + charset, tc);
77+
}
78+
catch (CharacterCodingException e) {
79+
throw ExceptionHandling.dieInternal(tc, e);
80+
}
81+
}
6882

6983
String normalized = Normalizer.normalize(
7084
decodedBuffer(target),
@@ -95,7 +109,15 @@ public synchronized String takeAvailableChars(ThreadContext tc) {
95109
int maxChars = availableDecodedChars() + availableUndecodedBytes();
96110
CharBuffer target = CharBuffer.allocate(maxChars);
97111
eatAllDecodedChars(target);
98-
eatUndecodedBytes(target, true);
112+
try {
113+
eatUndecodedBytes(target, true);
114+
}
115+
catch (MalformedInputException e) {
116+
Ops.die_s("Will not decode invalid " + charset, tc);
117+
}
118+
catch (CharacterCodingException e) {
119+
throw ExceptionHandling.dieInternal(tc, e);
120+
}
99121

100122
String normalized = Normalizer.normalize(
101123
decodedBuffer(target),
@@ -116,7 +138,15 @@ public synchronized String takeAllChars(ThreadContext tc) {
116138
if (toDecode != null) {
117139
if (toDecode.size() == 0)
118140
toDecode.add(ByteBuffer.allocate(0));
119-
eatUndecodedBytes(target, true);
141+
try {
142+
eatUndecodedBytes(target, true);
143+
}
144+
catch (MalformedInputException e) {
145+
Ops.die_s("Will not decode invalid " + charset, tc);
146+
}
147+
catch (CharacterCodingException e) {
148+
throw ExceptionHandling.dieInternal(tc, e);
149+
}
120150
decoder.flush(target);
121151
decoder.reset();
122152
}
@@ -153,7 +183,13 @@ public synchronized String takeLine(ThreadContext tc, boolean chomp, boolean eof
153183
/* Otherwise decode one of them. */
154184
ByteBuffer decodee = toDecode.get(0);
155185
CharBuffer target = CharBuffer.allocate(decodee.limit());
156-
decoder.decode(decodee, target, eof && toDecode.size() == 1);
186+
187+
CoderResult result = decoder.decode(decodee, target, eof && toDecode.size() == 1);
188+
/* TODO It looks like we read binary data with UTF_8 during
189+
* normal operation; don't die then. */
190+
if (result.isMalformed() && charset != StandardCharsets.UTF_8)
191+
Ops.die_s("Will not decode invalid " + charset, tc);
192+
157193
decoded.add(decodedBuffer(target));
158194
if (decodee.remaining() == 0)
159195
toDecode.remove(0);
@@ -262,11 +298,15 @@ private void eatDecodedChars(CharBuffer target, int n) {
262298
}
263299
}
264300

265-
private void eatUndecodedBytes(CharBuffer target, boolean eof) {
301+
private void eatUndecodedBytes(CharBuffer target, boolean eof) throws CharacterCodingException {
266302
if (toDecode != null) {
267303
while (toDecode.size() > 0) {
268304
ByteBuffer use = toDecode.get(0);
269-
decoder.decode(use, target, eof && toDecode.size() == 1);
305+
306+
CoderResult result = decoder.decode(use, target, eof && toDecode.size() == 1);
307+
if (result.isError())
308+
result.throwException();
309+
270310
if (use.position() == use.limit())
271311
toDecode.remove(0);
272312
else

0 commit comments

Comments
 (0)