Skip to content

Commit 9c3432e

Browse files
committed
strict handling of byte[] -> String encoding error
1 parent 3ebb46c commit 9c3432e

File tree

6 files changed

+166
-17
lines changed

6 files changed

+166
-17
lines changed

src/main/java/org/msgpack/packer/MessagePackPacker.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@
2222
import java.io.OutputStream;
2323
import java.nio.ByteBuffer;
2424
import java.math.BigInteger;
25+
import java.nio.charset.Charset;
26+
import java.nio.charset.CharacterCodingException;
27+
import java.nio.charset.CharsetEncoder;
28+
import java.nio.charset.CodingErrorAction;
29+
import java.nio.charset.MalformedInputException;
2530
import org.msgpack.io.Output;
2631
import org.msgpack.io.StreamOutput;
2732
import org.msgpack.MessagePack;
@@ -30,6 +35,7 @@
3035

3136
public class MessagePackPacker extends AbstractPacker {
3237
protected final Output out;
38+
protected CharsetEncoder encoder;
3339

3440
private PackerStack stack = new PackerStack();
3541

@@ -43,6 +49,9 @@ public MessagePackPacker(MessagePack msgpack, OutputStream stream) {
4349

4450
protected MessagePackPacker(MessagePack msgpack, Output out) {
4551
super(msgpack);
52+
this.encoder = Charset.forName("UTF-8").newEncoder().
53+
onMalformedInput(CodingErrorAction.REPORT).
54+
onUnmappableCharacter(CodingErrorAction.REPORT);
4655
this.out = out;
4756
}
4857

@@ -235,12 +244,12 @@ public void writeByteBuffer(ByteBuffer bb) throws IOException {
235244

236245
@Override
237246
public void writeString(String s) throws IOException {
238-
// TODO encoding error
239247
byte[] b;
240248
try {
249+
// TODO encoding error?
241250
b = s.getBytes("UTF-8");
242251
} catch (UnsupportedEncodingException ex) {
243-
throw new MessageTypeException();
252+
throw new MessageTypeException(ex);
244253
}
245254
writeByteArray(b, 0, b.length);
246255
stack.reduceCount();

src/main/java/org/msgpack/type/ByteArrayRawValueImpl.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@
2020
import java.util.Arrays;
2121
import java.io.UnsupportedEncodingException;
2222
import java.io.IOException;
23+
import java.nio.ByteBuffer;
24+
import java.nio.charset.Charset;
25+
import java.nio.charset.CharacterCodingException;
26+
import java.nio.charset.CharsetDecoder;
27+
import java.nio.charset.CodingErrorAction;
28+
import java.nio.charset.MalformedInputException;
2329
import org.msgpack.packer.Packer;
2430
import org.msgpack.MessageTypeException;
2531

@@ -52,11 +58,13 @@ public byte[] getByteArray() {
5258
}
5359

5460
public String getString() {
55-
// TODO encoding error
61+
CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder().
62+
onMalformedInput(CodingErrorAction.REPORT).
63+
onUnmappableCharacter(CodingErrorAction.REPORT);
5664
try {
57-
return new String(bytes, "UTF-8");
58-
} catch (UnsupportedEncodingException ex) {
59-
throw new MessageTypeException();
65+
return decoder.decode(ByteBuffer.wrap(bytes)).toString();
66+
} catch (CharacterCodingException ex) {
67+
throw new MessageTypeException(ex);
6068
}
6169
}
6270

src/main/java/org/msgpack/type/StringRawValueImpl.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,11 @@ class StringRawValueImpl extends AbstractRawValue {
3131
}
3232

3333
public byte[] getByteArray() {
34-
// TODO encoding error
3534
try {
35+
// TODO encoding error?
3636
return string.getBytes("UTF-8");
3737
} catch (UnsupportedEncodingException ex) {
38-
throw new MessageTypeException();
38+
throw new MessageTypeException(ex);
3939
}
4040
}
4141

src/main/java/org/msgpack/unpacker/AbstractUnpacker.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,6 @@ public void readMapEnd() throws IOException {
5050
}
5151

5252

53-
public String readString() throws IOException {
54-
// TODO encoding exception
55-
return new String(readByteArray(), "UTF-8");
56-
}
57-
5853
public UnpackerIterator iterator() {
5954
return new UnpackerIterator(this);
6055
}

src/main/java/org/msgpack/unpacker/StringAccept.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.nio.charset.CharsetDecoder;
2525
import java.nio.charset.CodingErrorAction;
2626
import java.nio.charset.MalformedInputException;
27+
import org.msgpack.MessageTypeException;
2728

2829

2930
final class StringAccept extends Accept {
@@ -38,8 +39,11 @@ public StringAccept() {
3839

3940
@Override
4041
void acceptRaw(byte[] raw) {
41-
// TODO encoding error
42-
this.value = new String(raw);
42+
try {
43+
this.value = decoder.decode(ByteBuffer.wrap(raw)).toString();
44+
} catch (CharacterCodingException ex) {
45+
throw new MessageTypeException(ex);
46+
}
4347
}
4448

4549
@Override
@@ -49,8 +53,11 @@ void acceptEmptyRaw() {
4953

5054
@Override
5155
public void refer(ByteBuffer bb, boolean gift) throws IOException {
52-
// TODO encoding error
53-
this.value = decoder.decode(bb).toString();
56+
try {
57+
this.value = decoder.decode(bb).toString();
58+
} catch (CharacterCodingException ex) {
59+
throw new MessageTypeException(ex);
60+
}
5461
}
5562
}
5663

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
package org.msgpack.unpacker;
2+
3+
import static org.junit.Assert.assertArrayEquals;
4+
import static org.junit.Assert.assertEquals;
5+
import static org.junit.Assert.assertTrue;
6+
import static org.junit.Assert.fail;
7+
8+
import java.math.BigInteger;
9+
import java.util.ArrayList;
10+
import java.util.HashMap;
11+
import java.util.Iterator;
12+
import java.util.List;
13+
import java.util.Map;
14+
import java.io.ByteArrayInputStream;
15+
import java.io.ByteArrayOutputStream;
16+
import java.nio.charset.CharacterCodingException;
17+
18+
import org.junit.Test;
19+
import org.msgpack.MessagePack;
20+
import org.msgpack.JSON;
21+
import org.msgpack.MessageTypeException;
22+
import org.msgpack.packer.Packer;
23+
import org.msgpack.packer.BufferPacker;
24+
import org.msgpack.packer.JSONPacker;
25+
import org.msgpack.unpacker.Unpacker;
26+
import org.msgpack.unpacker.BufferUnpacker;
27+
import org.msgpack.unpacker.Converter;
28+
import org.msgpack.type.Value;
29+
import org.msgpack.type.RawValue;
30+
import org.msgpack.type.ValueFactory;
31+
32+
public class TestMalformedEncoding {
33+
private byte[][] malforms = new byte[][] {
34+
{ (byte)0xc0, (byte)0xaf }, // '/' in 2 bytes
35+
{ (byte)0xe0, (byte)0x80, (byte)0xaf } // '/' in 3 bytes
36+
};
37+
38+
@Test
39+
public void testRawValueGetString() throws Exception {
40+
for(byte[] malform : malforms) {
41+
RawValue r = ValueFactory.rawValue(malform);
42+
try {
43+
r.getString();
44+
fail("no exception");
45+
} catch (MessageTypeException expected) {
46+
}
47+
byte[] a = r.getByteArray();
48+
assertArrayEquals(malform, a);
49+
}
50+
}
51+
52+
@Test
53+
public void testBufferUnpackerUnpackString() throws Exception {
54+
for(byte[] malform : malforms) {
55+
MessagePack msgpack = new MessagePack();
56+
BufferPacker pk = msgpack.createBufferPacker();
57+
pk.writeByteArray(malform);
58+
byte[] b = pk.toByteArray();
59+
Unpacker u = msgpack.createBufferUnpacker(b);
60+
try {
61+
u.readString();
62+
fail("no exception");
63+
} catch (MessageTypeException expected) {
64+
}
65+
byte[] a = u.readByteArray();
66+
assertArrayEquals(malform, a);
67+
}
68+
}
69+
70+
@Test
71+
public void testUnpackerUnpackString() throws Exception {
72+
for(byte[] malform : malforms) {
73+
MessagePack msgpack = new MessagePack();
74+
BufferPacker pk = msgpack.createBufferPacker();
75+
pk.writeByteArray(malform);
76+
byte[] b = pk.toByteArray();
77+
Unpacker u = msgpack.createUnpacker(new ByteArrayInputStream(b));
78+
try {
79+
u.readString();
80+
fail("no exception");
81+
} catch (MessageTypeException expected) {
82+
}
83+
byte[] a = u.readByteArray();
84+
assertArrayEquals(malform, a);
85+
}
86+
}
87+
88+
@Test
89+
public void testConverterUnpackString() throws Exception {
90+
for(byte[] malform : malforms) {
91+
MessagePack msgpack = new MessagePack();
92+
RawValue r = ValueFactory.rawValue(malform);
93+
Converter u = new Converter(msgpack, r);
94+
try {
95+
u.readString();
96+
fail("no exception");
97+
} catch (MessageTypeException expected) {
98+
}
99+
byte[] a = u.readByteArray();
100+
assertArrayEquals(malform, a);
101+
}
102+
}
103+
104+
@Test
105+
public void testJSONPackerWriteString() throws Exception {
106+
for(byte[] malform : malforms) {
107+
JSON json = new JSON();
108+
Packer pk = json.createPacker(new ByteArrayOutputStream());
109+
try {
110+
pk.writeByteArray(malform);
111+
fail("no exception");
112+
} catch (CharacterCodingException expected) {
113+
}
114+
}
115+
}
116+
117+
@Test
118+
public void testJSONBufferPackerWriteString() throws Exception {
119+
for(byte[] malform : malforms) {
120+
JSON json = new JSON();
121+
Packer pk = json.createBufferPacker();
122+
try {
123+
pk.writeByteArray(malform);
124+
fail("no exception");
125+
} catch (CharacterCodingException expected) {
126+
}
127+
}
128+
}
129+
}
130+

0 commit comments

Comments
 (0)