Skip to content

Commit 554f8db

Browse files
committed
Fix #307
1 parent d32c85f commit 554f8db

File tree

4 files changed

+179
-36
lines changed

4 files changed

+179
-36
lines changed

release-notes/CREDITS

+5-1
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,12 @@ Lokesh Kumar N (LokeshN@github)
7979
* Contributed #209: Make use of `_allowMultipleMatches` in `FilteringParserDelegate`
8080
(2.7.4)
8181

82-
8382
Tanguy Leroux (tlrx@github)
8483
* Reported, contributed fix for #280: FilteringGeneratorDelegate.writeUTF8String()
8584
should delegate to writeUTF8String()
8685
(2.7.5)
86+
87+
Mike Naseef (mtnaseef@github)
88+
* Reported #307: JsonGenerationException: Split surrogate on writeRaw() input thrown for
89+
input of a certain size
90+
(2.7.7)

release-notes/VERSION

+6
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ JSON library.
1414
=== Releases ===
1515
------------------------------------------------------------------------
1616

17+
2.7.7 (not yet released)
18+
19+
#307: JsonGenerationException: Split surrogate on writeRaw() input thrown for
20+
input of a certain size
21+
(reported by Mike N)
22+
1723
2.7.6 (23-Jul-2016)
1824

1925
- Clean up of FindBugs reported possible issues.

src/main/java/com/fasterxml/jackson/core/json/UTF8JsonGenerator.java

+79-35
Original file line numberDiff line numberDiff line change
@@ -515,39 +515,50 @@ public void writeUTF8String(byte[] text, int offset, int len) throws IOException
515515
*/
516516

517517
@Override
518-
public void writeRaw(String text)
519-
throws IOException, JsonGenerationException
520-
{
521-
int start = 0;
522-
int len = text.length();
523-
while (len > 0) {
524-
char[] buf = _charBuffer;
525-
final int blen = buf.length;
526-
final int len2 = (len < blen) ? len : blen;
527-
text.getChars(start, start+len2, buf, 0);
528-
writeRaw(buf, 0, len2);
529-
start += len2;
530-
len -= len2;
531-
}
518+
public void writeRaw(String text) throws IOException {
519+
writeRaw(text, 0, text.length());
532520
}
533521

534522
@Override
535-
public void writeRaw(String text, int offset, int len)
536-
throws IOException, JsonGenerationException
523+
public void writeRaw(String text, int offset, int len) throws IOException
537524
{
525+
final char[] buf = _charBuffer;
526+
527+
// minor optimization: see if we can just get and copy
528+
if (len <= buf.length) {
529+
text.getChars(offset, offset+len, buf, 0);
530+
_writeRawSegment(buf, 0, len);
531+
return;
532+
}
533+
534+
// If not, need segmented approach. For speed, let's also use input buffer
535+
// size that is guaranteed to fit in output buffer; each char can expand to
536+
// at most 3 bytes, so at most 1/3 of buffer size.
537+
final int maxChunk = (_outputEnd >> 2) + (_outputEnd >> 4); // == (1/4 + 1/16) == 5/16
538+
final int maxBytes = maxChunk * 3;
539+
538540
while (len > 0) {
539-
char[] buf = _charBuffer;
540-
final int blen = buf.length;
541-
final int len2 = (len < blen) ? len : blen;
541+
int len2 = Math.min(maxChunk, len);
542542
text.getChars(offset, offset+len2, buf, 0);
543-
writeRaw(buf, 0, len2);
543+
if ((_outputTail + maxBytes) > _outputEnd) {
544+
_flushBuffer();
545+
}
546+
// If this is NOT the last segment and if the last character looks like
547+
// split surrogate second half, drop it
548+
if (len > 0) {
549+
char ch = buf[len2-1];
550+
if ((ch >= SURR1_FIRST) && (ch <= SURR1_LAST)) {
551+
--len2;
552+
}
553+
}
554+
_writeRawSegment(buf, 0, len2);
544555
offset += len2;
545556
len -= len2;
546557
}
547558
}
548559

549560
@Override
550-
public void writeRaw(SerializableString text) throws IOException, JsonGenerationException
561+
public void writeRaw(SerializableString text) throws IOException
551562
{
552563
byte[] raw = text.asUnquotedUTF8();
553564
if (raw.length > 0) {
@@ -567,8 +578,7 @@ public void writeRawValue(SerializableString text) throws IOException {
567578

568579
// @TODO: rewrite for speed...
569580
@Override
570-
public final void writeRaw(char[] cbuf, int offset, int len)
571-
throws IOException, JsonGenerationException
581+
public final void writeRaw(char[] cbuf, int offset, int len) throws IOException
572582
{
573583
// First: if we have 3 x charCount spaces, we know it'll fit just fine
574584
{
@@ -610,8 +620,7 @@ public final void writeRaw(char[] cbuf, int offset, int len)
610620
}
611621

612622
@Override
613-
public void writeRaw(char ch)
614-
throws IOException, JsonGenerationException
623+
public void writeRaw(char ch) throws IOException
615624
{
616625
if ((_outputTail + 3) >= _outputEnd) {
617626
_flushBuffer();
@@ -631,14 +640,14 @@ public void writeRaw(char ch)
631640
* Helper method called when it is possible that output of raw section
632641
* to output may cross buffer boundary
633642
*/
634-
private final void _writeSegmentedRaw(char[] cbuf, int offset, int len)
635-
throws IOException, JsonGenerationException
643+
private final void _writeSegmentedRaw(char[] cbuf, int offset, int len) throws IOException
636644
{
637645
final int end = _outputEnd;
638646
final byte[] bbuf = _outputBuffer;
647+
final int inputEnd = offset + len;
639648

640649
main_loop:
641-
while (offset < len) {
650+
while (offset < inputEnd) {
642651
inner_loop:
643652
while (true) {
644653
int ch = (int) cbuf[offset];
@@ -650,7 +659,7 @@ private final void _writeSegmentedRaw(char[] cbuf, int offset, int len)
650659
_flushBuffer();
651660
}
652661
bbuf[_outputTail++] = (byte) ch;
653-
if (++offset >= len) {
662+
if (++offset >= inputEnd) {
654663
break main_loop;
655664
}
656665
}
@@ -662,11 +671,45 @@ private final void _writeSegmentedRaw(char[] cbuf, int offset, int len)
662671
bbuf[_outputTail++] = (byte) (0xc0 | (ch >> 6));
663672
bbuf[_outputTail++] = (byte) (0x80 | (ch & 0x3f));
664673
} else {
665-
offset = _outputRawMultiByteChar(ch, cbuf, offset, len);
674+
offset = _outputRawMultiByteChar(ch, cbuf, offset, inputEnd);
666675
}
667676
}
668677
}
669-
678+
679+
/**
680+
* Helper method that is called for segmented write of raw content
681+
* when explicitly outputting a segment of longer thing.
682+
* Caller has to take care of ensuring there's no split surrogate
683+
* pair at the end (that is, last char can not be first part of a
684+
* surrogate char pair).
685+
*
686+
* @since 2.8.2
687+
*/
688+
private void _writeRawSegment(char[] cbuf, int offset, int end) throws IOException
689+
{
690+
main_loop:
691+
while (offset < end) {
692+
inner_loop:
693+
while (true) {
694+
int ch = (int) cbuf[offset];
695+
if (ch > 0x7F) {
696+
break inner_loop;
697+
}
698+
_outputBuffer[_outputTail++] = (byte) ch;
699+
if (++offset >= end) {
700+
break main_loop;
701+
}
702+
}
703+
char ch = cbuf[offset++];
704+
if (ch < 0x800) { // 2-byte?
705+
_outputBuffer[_outputTail++] = (byte) (0xc0 | (ch >> 6));
706+
_outputBuffer[_outputTail++] = (byte) (0x80 | (ch & 0x3f));
707+
} else {
708+
offset = _outputRawMultiByteChar(ch, cbuf, offset, end);
709+
}
710+
}
711+
}
712+
670713
/*
671714
/**********************************************************
672715
/* Output method implementations, base64-encoded binary
@@ -1873,18 +1916,19 @@ private final int _readMore(InputStream in,
18731916
* 1- and 2-byte UTF-8 encodings, when outputting "raw"
18741917
* text (meaning it is not to be escaped or quoted)
18751918
*/
1876-
private final int _outputRawMultiByteChar(int ch, char[] cbuf, int inputOffset, int inputLen)
1919+
private final int _outputRawMultiByteChar(int ch, char[] cbuf, int inputOffset, int inputEnd)
18771920
throws IOException
18781921
{
18791922
// Let's handle surrogates gracefully (as 4 byte output):
18801923
if (ch >= SURR1_FIRST) {
18811924
if (ch <= SURR2_LAST) { // yes, outside of BMP
18821925
// Do we have second part?
1883-
if (inputOffset >= inputLen || cbuf == null) { // nope... have to note down
1884-
_reportError("Split surrogate on writeRaw() input (last character)");
1926+
if (inputOffset >= inputEnd || cbuf == null) { // nope... have to note down
1927+
_reportError(String.format(
1928+
"Split surrogate on writeRaw() input (last character): first character 0x%4x", ch));
18851929
}
18861930
_outputSurrogates(ch, cbuf[inputOffset]);
1887-
return (inputOffset+1);
1931+
return inputOffset+1;
18881932
}
18891933
}
18901934
final byte[] bbuf = _outputBuffer;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package com.fasterxml.jackson.core.json;
2+
3+
import java.io.ByteArrayOutputStream;
4+
import com.fasterxml.jackson.core.JsonFactory;
5+
import com.fasterxml.jackson.core.JsonGenerator;
6+
7+
public class RawValueWithSurrogatesTest
8+
extends com.fasterxml.jackson.core.BaseTest
9+
{
10+
final String SURROGATES_307;
11+
{
12+
// This one fails:
13+
String msg ="{'xxxxxxx':{'xxxx':'xxxxxxxxx','xx':'xxxxxxxxxxxxxxxxxxx','xxxxxxxxx':'xxxx://xxxxxxx.xxx',"
14+
+"'xxxxxx':{'xxxx':'xxxxxxxxxxx','xxxxxxxx':{'xxxxxxxxxxx':'xx','xxxxxxxxxx':'xx-xx'}},"
15+
+"'xxxxx':[{'xxxx':'xxxx','xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍'}]},"
16+
+"'xxxxxxxxxxx':[{'xxxxxxx':'xxxxxx','xxxxxxxx':[{'xxxxxx':x,'xxxxxx':xxx,"
17+
+"'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍',"
18+
+"'xxxxxx':{'xxxxxx':xx,'xxxxxx':x,'xxxx':'xxxxx'}},"
19+
+"{'xxxxxx':x,'xxxxxx':xxx,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍'"
20+
+",'xxxxxx':{'xxxxxx':xxx,'xxxxxx':x,'xxxx':'xxxxx'}}]},{'xxxxxxxxxxx':'xxxxxx','xxxxxxxx':[{'xxxxxx':x,'xxxxxx':xxx,"
21+
+"'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍',"
22+
+"'xxxxxx':{'xxxxxx':xx,'xxxxxx':x,'xxxx':'xxxxx'}},"
23+
+"{'xxxxxx':x,'xxxxxx':xxx,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍',"
24+
+"'xxxxxx':{'xxxxxx':xxx,'xxxxxx':x,'xxxx':'xxxxx'}}]},{'xxxxxxxxxxx':'xxxxxx','xxxxxxxx':[{'xxxxxx':x,'xxxxxx':xxx,"
25+
+"'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍',"
26+
+"'xxxxxx':{'xxxxxx':xx,'xxxxxx':x,'xxxx':'xxxxx'}},{'xxxxxx':x,'xxxxxx':xxx,"
27+
+"'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍',"
28+
+"'xxxxxx':{'xxxxxx':xxx,'xxxxxx':x,'xxxx':'xxxxx'}}]},{'xxxxxxxxxxx':'xxxxxx','xxxxxxxx':[{'xxxxxx':x,'xxxxxx':xxx,"
29+
+"'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍',"
30+
+"'xxxxxx':{'xxxxxx':xx,'xxxxxx':x,'xxxx':'xxxxx'}},{'xxxxxx':x,'xxxxxx':xxx,"
31+
+"'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍',"
32+
+"'xxxxxx':{'xxxxxx':xxx,'xxxxxx':x,'xxxx':'xxxxx'}}]},{'xxxxxxxxxxx':'xxxxxx','xxxxxxxx':"
33+
+"[{'xxxxxx':3,'xxxxxx':123,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍',"
34+
+"'xxxxxx':{'xxxxxx':24,'xxxxxx':4,'xxxx':'xxxxx'}},{'xxxxxx':0,'xxxxxx':123,"
35+
+"'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍',"
36+
+"'xxxxxx':{'xxxxxx':123,'xxxxxx':1,'xxxx':'xxxxx'}}]},{'xxxxxxxxxxx':'xxxxxx','xxxxxxxx':[{'xxxxxx':1,'xxxxxx':123,"
37+
+"'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍','xxxxxx':{'xxxxxx':xx,'xxxxxx':x,'xxxx':'xxxxx'}},"
38+
+"{'xxxxxx':x,'xxxxxx':123,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍',"
39+
+"'xxxxxx':{'xxxxxx':xxx,'xxxxxx':x,'xxxx':'xxxxx'}}]},{'xxxxxxxxxxx':'xxxxx','xxxxxxxx':[{'xxxxxx':x,'xxxxxx':xxx,"
40+
+"'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍',"
41+
+"'xxxxxx':{'xxxxxx':xx,'xxxxxx':x,'xxxx':'xxxxx'}},{'xxxxxx':x,'xxxxxx':xxx,"
42+
+"'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍',"
43+
+"'xxxxxx':{'xxxxxx':xxx,'xxxxxx':x,'xxxx':'xxxxx'}}]}]}";
44+
// This one works:
45+
// String msg ="{'xxx':{'xxxx':'xxxxxxxxx','xx':'xxxxxxxxxxxxxxxxxxx','xxxxxxxxx':'xxxx://xxxxxxx.xxx','xxxxxx':{'xxxx':'xxxxxxxxxxx','xxxxxxxx':{'xxxxxxxxxxx':'xx','xxxxxxxxxx':'xx-xx'}},'xxxxx':[{'xxxx':'xxxx','xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍'}]},'xxxxxxxxxxx':[{'xxxxxxx':'xxxxxx','xxxxxxxx':[{'xxxxxx':x,'xxxxxx':xxx,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍','xxxxxx':{'xxxxxx':xx,'xxxxxx':x,'xxxx':'xxxxx'}},{'xxxxxx':x,'xxxxxx':xxx,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍','xxxxxx':{'xxxxxx':xxx,'xxxxxx':x,'xxxx':'xxxxx'}}]},{'xxxxxxxxxxx':'xxxxxx','xxxxxxxx':[{'xxxxxx':x,'xxxxxx':xxx,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍','xxxxxx':{'xxxxxx':xx,'xxxxxx':x,'xxxx':'xxxxx'}},{'xxxxxx':x,'xxxxxx':xxx,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍','xxxxxx':{'xxxxxx':xxx,'xxxxxx':x,'xxxx':'xxxxx'}}]},{'xxxxxxxxxxx':'xxxxxx','xxxxxxxx':[{'xxxxxx':x,'xxxxxx':xxx,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍','xxxxxx':{'xxxxxx':xx,'xxxxxx':x,'xxxx':'xxxxx'}},{'xxxxxx':x,'xxxxxx':xxx,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍','xxxxxx':{'xxxxxx':xxx,'xxxxxx':x,'xxxx':'xxxxx'}}]},{'xxxxxxxxxxx':'xxxxxx','xxxxxxxx':[{'xxxxxx':x,'xxxxxx':xxx,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍','xxxxxx':{'xxxxxx':xx,'xxxxxx':x,'xxxx':'xxxxx'}},{'xxxxxx':x,'xxxxxx':xxx,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍','xxxxxx':{'xxxxxx':xxx,'xxxxxx':x,'xxxx':'xxxxx'}}]},{'xxxxxxxxxxx':'xxxxxx','xxxxxxxx':[{'xxxxxx':x,'xxxxxx':xxx,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍','xxxxxx':{'xxxxxx':xx,'xxxxxx':x,'xxxx':'xxxxx'}},{'xxxxxx':x,'xxxxxx':xxx,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍','xxxxxx':{'xxxxxx':xxx,'xxxxxx':x,'xxxx':'xxxxx'}}]},{'xxxxxxxxxxx':'xxxxxx','xxxxxxxx':[{'xxxxxx':x,'xxxxxx':xxx,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍','xxxxxx':{'xxxxxx':xx,'xxxxxx':x,'xxxx':'xxxxx'}},{'xxxxxx':x,'xxxxxx':xxx,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍','xxxxxx':{'xxxxxx':xxx,'xxxxxx':x,'xxxx':'xxxxx'}}]},{'xxxxxxxxxxx':'xxxxx','xxxxxxxx':[{'xxxxxx':x,'xxxxxx':xxx,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍','xxxxxx':{'xxxxxx':xx,'xxxxxx':x,'xxxx':'xxxxx'}},{'xxxxxx':x,'xxxxxx':xxx,'xxxx':'xx xxxxxxxxxxx: xxxxxxx xxxxxx xxxxxxxxxxxxx xxxxx xxxxxx. xxxxx xxxxxx xxxxx xxxxx. xx xxx xx xxxx xxx xxxx. xxxx xxxxx xxx xxxxxxxx xxxxx xxxxxx xxxxxxx😆👍','xxxxxx':{'xxxxxx':xxx,'xxxxxx':x,'xxxx':'xxxxx'}}]}]}";
46+
47+
SURROGATES_307 = aposToQuotes(msg);
48+
}
49+
50+
private final JsonFactory JSON_F = new JsonFactory();
51+
52+
// for [jackson-core#307]
53+
public void testRawWithSurrogatesString() throws Exception {
54+
_testRawWithSurrogatesString(false);
55+
}
56+
57+
// for [jackson-core#307]
58+
public void testRawWithSurrogatesCharArray() throws Exception {
59+
_testRawWithSurrogatesString(true);
60+
}
61+
62+
private void _testRawWithSurrogatesString(boolean useCharArray) throws Exception
63+
{
64+
// boundaries are not exact, may vary, so use this:
65+
66+
final int OFFSET = 3;
67+
final int COUNT = 100;
68+
69+
for (int i = OFFSET; i < COUNT; ++i) {
70+
StringBuilder sb = new StringBuilder(1000);
71+
for (int j = 0; j < i; ++j) {
72+
sb.append(' ');
73+
}
74+
sb.append(SURROGATES_307);
75+
final String text = sb.toString();
76+
ByteArrayOutputStream out = new ByteArrayOutputStream(1000);
77+
JsonGenerator g = JSON_F.createGenerator(out);
78+
if (useCharArray) {
79+
char[] ch = text.toCharArray();
80+
g.writeRawValue(ch, OFFSET, ch.length - OFFSET);
81+
} else {
82+
g.writeRawValue(text, OFFSET, text.length() - OFFSET);
83+
}
84+
g.close();
85+
byte[] b = out.toByteArray();
86+
assertNotNull(b);
87+
}
88+
}
89+
}

0 commit comments

Comments
 (0)