2
2
3
3
import java .nio .ByteBuffer ;
4
4
import java .nio .CharBuffer ;
5
+ import java .nio .charset .CharacterCodingException ;
5
6
import java .nio .charset .Charset ;
6
7
import java .nio .charset .CharsetDecoder ;
8
+ import java .nio .charset .CoderResult ;
9
+ import java .nio .charset .MalformedInputException ;
10
+ import java .nio .charset .StandardCharsets ;
7
11
import java .text .Normalizer ;
8
12
import java .util .ArrayList ;
9
13
import java .util .List ;
10
14
import org .perl6 .nqp .runtime .Buffers ;
11
15
import org .perl6 .nqp .runtime .ExceptionHandling ;
16
+ import org .perl6 .nqp .runtime .Ops ;
12
17
import org .perl6 .nqp .runtime .ThreadContext ;
13
18
import org .perl6 .nqp .sixmodel .SixModelObject ;
14
19
import org .perl6 .nqp .sixmodel .StorageSpec ;
@@ -63,8 +68,17 @@ public synchronized String takeChars(ThreadContext tc, long chars, boolean eof)
63
68
64
69
CharBuffer target = CharBuffer .allocate ((int )chars + 1 );
65
70
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
+ }
68
82
69
83
String normalized = Normalizer .normalize (
70
84
decodedBuffer (target ),
@@ -95,7 +109,15 @@ public synchronized String takeAvailableChars(ThreadContext tc) {
95
109
int maxChars = availableDecodedChars () + availableUndecodedBytes ();
96
110
CharBuffer target = CharBuffer .allocate (maxChars );
97
111
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
+ }
99
121
100
122
String normalized = Normalizer .normalize (
101
123
decodedBuffer (target ),
@@ -116,7 +138,15 @@ public synchronized String takeAllChars(ThreadContext tc) {
116
138
if (toDecode != null ) {
117
139
if (toDecode .size () == 0 )
118
140
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
+ }
120
150
decoder .flush (target );
121
151
decoder .reset ();
122
152
}
@@ -153,7 +183,13 @@ public synchronized String takeLine(ThreadContext tc, boolean chomp, boolean eof
153
183
/* Otherwise decode one of them. */
154
184
ByteBuffer decodee = toDecode .get (0 );
155
185
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
+
157
193
decoded .add (decodedBuffer (target ));
158
194
if (decodee .remaining () == 0 )
159
195
toDecode .remove (0 );
@@ -262,11 +298,15 @@ private void eatDecodedChars(CharBuffer target, int n) {
262
298
}
263
299
}
264
300
265
- private void eatUndecodedBytes (CharBuffer target , boolean eof ) {
301
+ private void eatUndecodedBytes (CharBuffer target , boolean eof ) throws CharacterCodingException {
266
302
if (toDecode != null ) {
267
303
while (toDecode .size () > 0 ) {
268
304
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
+
270
310
if (use .position () == use .limit ())
271
311
toDecode .remove (0 );
272
312
else
0 commit comments