Skip to content

Commit 9ba6852

Browse files
committed
Fix #90
1 parent a4468c0 commit 9ba6852

File tree

6 files changed

+105
-43
lines changed

6 files changed

+105
-43
lines changed

release-notes/CREDITS-2.x

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,7 @@ Andrey Somov (asomov@github)
3737
* Contributed #101: Use latest SnakeYAML version 1.23 and get rid of deprecated methods
3838
(2.10.0)
3939

40+
Tanguy Leroux (tlrx@github)
41+
42+
* Reported #90: Exception when decoding Jackson-encoded `Base64` binary value in YAML
43+
(2.10.0)

release-notes/VERSION-2.x

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ Modules:
1010

1111
2.10.0 (not yet released)
1212

13-
#101: Use latest SnakeYAML version 1.23 and get rid of deprecated methods
13+
#90: Exception when decoding Jackson-encoded `Base64` binary value in YAML
14+
(reported by Tanguy L)
15+
#101: (yaml) Use latest SnakeYAML version 1.23 and get rid of deprecated methods
1416
(contributed by Andrey S)
15-
#108: Add new `CsvParser.Feature.ALLOW_COMMENTS` to replace deprecated
17+
#108: (yaml) Add new `CsvParser.Feature.ALLOW_COMMENTS` to replace deprecated
1618
`JsonParser.Feature.ALLOW_YAML_COMMENTS`
1719

1820
2.9.9 (not yet released)

yaml/src/main/java/com/fasterxml/jackson/dataformat/yaml/YAMLGenerator.java

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -835,7 +835,8 @@ private void _writeScalarBinary(Base64Variant b64variant,
835835
if (b64variant == Base64Variants.getDefaultVariant()) {
836836
b64variant = Base64Variants.MIME;
837837
}
838-
String encoded = b64variant.encode(data);
838+
final String lf = _lf();
839+
String encoded = _base64encode(b64variant, data, lf);
839840
_emitter.emit(new ScalarEvent(null, TAG_BINARY, EXPLICIT_TAGS, encoded,
840841
null, null, STYLE_BASE64));
841842
}
@@ -855,4 +856,42 @@ protected ScalarEvent _scalarEvent(String value, DumperOptions.ScalarStyle style
855856
return new ScalarEvent(anchor, yamlTag, NO_TAGS, value,
856857
null, null, style);
857858
}
859+
860+
// // // 26-Feb-2019, tatu: Copied temporarily (for 2.10) from `Base64Variant` to prevent
861+
// // // hard dependency for same minor version
862+
863+
private String _base64encode(final Base64Variant b64v, final byte[] input, final String linefeed)
864+
{
865+
final int inputEnd = input.length;
866+
final StringBuilder sb = new StringBuilder(inputEnd + (inputEnd >> 2) + (inputEnd >> 3));
867+
868+
int chunksBeforeLF = b64v.getMaxLineLength() >> 2;
869+
870+
int inputPtr = 0;
871+
int safeInputEnd = inputEnd-3;
872+
873+
while (inputPtr <= safeInputEnd) {
874+
int b24 = ((int) input[inputPtr++]) << 8;
875+
b24 |= ((int) input[inputPtr++]) & 0xFF;
876+
b24 = (b24 << 8) | (((int) input[inputPtr++]) & 0xFF);
877+
b64v.encodeBase64Chunk(sb, b24);
878+
if (--chunksBeforeLF <= 0) {
879+
sb.append(linefeed);
880+
chunksBeforeLF = b64v.getMaxLineLength() >> 2;
881+
}
882+
}
883+
int inputLeft = inputEnd - inputPtr;
884+
if (inputLeft > 0) {
885+
int b24 = ((int) input[inputPtr++]) << 16;
886+
if (inputLeft == 2) {
887+
b24 |= (((int) input[inputPtr++]) & 0xFF) << 8;
888+
}
889+
b64v.encodeBase64Partial(sb, b24, inputLeft);
890+
}
891+
return sb.toString();
892+
}
893+
894+
protected String _lf() {
895+
return _outputOptions.getLineBreak().getString();
896+
}
858897
}

yaml/src/test/java/com/fasterxml/jackson/dataformat/yaml/deser/BinaryReadTest.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
package com.fasterxml.jackson.dataformat.yaml.deser;
22

3+
import java.io.ByteArrayOutputStream;
34
import java.io.IOException;
45
import java.util.Arrays;
6+
import java.util.Random;
57

68
import org.junit.Assert;
79

10+
import com.fasterxml.jackson.core.*;
11+
812
import com.fasterxml.jackson.databind.*;
913
import com.fasterxml.jackson.databind.node.JsonNodeType;
1014
import com.fasterxml.jackson.dataformat.yaml.ModuleTestBase;
@@ -41,4 +45,29 @@ public void testBinaryViaTree() throws Exception
4145
final byte[] expectedFileHeader = new byte[]{'G', 'I', 'F', '8', '9', 'a'};
4246
Assert.assertArrayEquals(expectedFileHeader, actualFileHeader);
4347
}
48+
49+
// [dataformats-text#90]
50+
public void testReadLongBinary() throws Exception {
51+
final byte[] data = new byte[1000];
52+
new Random(1234).nextBytes(data);
53+
54+
ByteArrayOutputStream os = new ByteArrayOutputStream();
55+
56+
try (JsonGenerator gen = MAPPER.getFactory().createGenerator(os)) {
57+
gen.writeStartObject();
58+
gen.writeBinaryField("data", data);
59+
gen.writeEndObject();
60+
gen.close();
61+
}
62+
63+
try (JsonParser parser = MAPPER.getFactory().createParser(os.toByteArray())) {
64+
assertEquals(JsonToken.START_OBJECT, parser.nextToken());
65+
assertEquals(JsonToken.FIELD_NAME, parser.nextToken());
66+
assertEquals("data", parser.currentName());
67+
assertEquals(JsonToken.VALUE_EMBEDDED_OBJECT, parser.nextToken());
68+
Assert.assertArrayEquals(data, parser.getBinaryValue());
69+
assertEquals(JsonToken.END_OBJECT, parser.nextToken());
70+
assertNull(parser.nextToken());
71+
}
72+
}
4473
}

yaml/src/test/java/com/fasterxml/jackson/dataformat/yaml/failing/ObjectId123Test.java

Lines changed: 0 additions & 40 deletions
This file was deleted.

yaml/src/test/java/com/fasterxml/jackson/dataformat/yaml/ser/BinaryWriteTest.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
package com.fasterxml.jackson.dataformat.yaml.ser;
22

3+
import java.io.StringWriter;
4+
import java.util.Arrays;
5+
36
import org.junit.Assert;
47

8+
import com.fasterxml.jackson.core.JsonGenerator;
59
import com.fasterxml.jackson.databind.*;
610
import com.fasterxml.jackson.databind.node.JsonNodeType;
711
import com.fasterxml.jackson.databind.node.ObjectNode;
@@ -26,4 +30,28 @@ public void testBinaryViaTree() throws Exception
2630
final byte[] b = data.binaryValue();
2731
Assert.assertArrayEquals(srcPayload, b);
2832
}
33+
34+
public void testWriteLongBinary() throws Exception {
35+
final int length = 200;
36+
final byte[] data = new byte[length];
37+
Arrays.fill(data, (byte) 1);
38+
39+
StringWriter w = new StringWriter();
40+
41+
try (JsonGenerator gen = MAPPER.getFactory().createGenerator(w)) {
42+
gen.writeStartObject();
43+
gen.writeBinaryField("array", data);
44+
gen.writeEndObject();
45+
gen.close();
46+
}
47+
48+
String yaml = w.toString();
49+
Assert.assertEquals("---\n" +
50+
"array: !!binary |-\n" +
51+
" AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB\n" +
52+
" AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB\n" +
53+
" AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB\n" +
54+
" AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE=\n", yaml);
55+
56+
}
2957
}

0 commit comments

Comments
 (0)