Skip to content

Commit

Permalink
Backport #603 fix, update release notes
Browse files Browse the repository at this point in the history
  • Loading branch information
fabienrenaud authored and cowtowncoder committed Feb 26, 2020
1 parent b2be2c4 commit 18819b1
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 11 deletions.
5 changes: 4 additions & 1 deletion release-notes/CREDITS-2.x
Expand Up @@ -196,9 +196,12 @@ David Nault (dnault@github)
(2.10.0)
Fabien Renaud (fabienrenaud@github)
* Reported, contributed fix fir #533: UTF-8 BOM not accounted for in
* Reported, contributed fix for #533: UTF-8 BOM not accounted for in
`JsonLocation.getByteOffset()`
(2.10.0)
* Reported, contributed fix for #603: 'JsonParser.getCurrentLocation()`
byte/char offset update incorrectly for big payloads
(2.10.3)

Todd O'Bryan (toddobryan@github)
* Contributed fix fox #455: Jackson reports wrong locations for JsonEOFException
Expand Down
2 changes: 2 additions & 0 deletions release-notes/VERSION-2.x
Expand Up @@ -18,6 +18,8 @@ JSON library.

#592: DataFormatMatcher#getMatchedFormatName throws NPE when no match exists
(reported by Scott L)
#603: 'JsonParser.getCurrentLocation()` byte/char offset update incorrectly for big payloads
(reported, fix contributed by Fabien R)
2.10.2 (05-Jan-2020)
Expand Down
Expand Up @@ -244,14 +244,10 @@ protected void _loadMoreGuaranteed() throws IOException {

protected boolean _loadMore() throws IOException
{
final int bufSize = _inputEnd;

if (_reader != null) {
int count = _reader.read(_inputBuffer, 0, _inputBuffer.length);
if (count > 0) {
_inputPtr = 0;
_inputEnd = count;

final int bufSize = _inputEnd;
_currInputProcessed += bufSize;
_currInputRowStart -= bufSize;

Expand All @@ -260,6 +256,9 @@ protected boolean _loadMore() throws IOException
// in negative value, which is fine as combine value remains unchanged.
_nameStartOffset -= bufSize;

_inputPtr = 0;
_inputEnd = count;

return true;
}
// End of input
Expand Down
Expand Up @@ -210,7 +210,6 @@ public Object getInputSource() {

protected final boolean _loadMore() throws IOException
{
final int bufSize = _inputEnd;
if (_inputStream != null) {
int space = _inputBuffer.length;
if (space == 0) { // only occurs when we've been closed
Expand All @@ -219,17 +218,19 @@ protected final boolean _loadMore() throws IOException

int count = _inputStream.read(_inputBuffer, 0, space);
if (count > 0) {
_inputPtr = 0;
_inputEnd = count;
final int bufSize = _inputEnd;

_currInputProcessed += _inputEnd;
_currInputRowStart -= _inputEnd;
_currInputProcessed += bufSize;
_currInputRowStart -= bufSize;

// 26-Nov-2015, tatu: Since name-offset requires it too, must offset
// this increase to avoid "moving" name-offset, resulting most likely
// in negative value, which is fine as combine value remains unchanged.
_nameStartOffset -= bufSize;

_inputPtr = 0;
_inputEnd = count;

return true;
}
// End of input
Expand Down
113 changes: 113 additions & 0 deletions src/test/java/com/fasterxml/jackson/core/read/LocationOffsetsTest.java
Expand Up @@ -2,6 +2,9 @@

import com.fasterxml.jackson.core.*;

import java.io.IOException;
import java.util.Random;

public class LocationOffsetsTest extends com.fasterxml.jackson.core.BaseTest
{
final JsonFactory JSON_F = new JsonFactory();
Expand Down Expand Up @@ -104,6 +107,45 @@ public void testOffsetWithoutInputOffset() throws Exception
p.close();
}

public void testWithLazyStringReadStreaming() throws Exception
{
_testWithLazyStringRead(MODE_READER);
_testWithLazyStringRead(MODE_INPUT_STREAM);
}

public void testWithLazyStringReadDataInput() throws Exception
{
// DataInput-backed reader does not track column, so can not
// verify much; but force finishToken() regardless
JsonParser p = createParser(JSON_F, MODE_DATA_INPUT, "[\"text\"]");
assertToken(JsonToken.START_ARRAY, p.nextToken());
assertToken(JsonToken.VALUE_STRING, p.nextToken());
assertEquals(1, p.getCurrentLocation().getLineNr());
p.finishToken();
assertEquals("text", p.getText());
p.close();
}

private void _testWithLazyStringRead(int readMode) throws Exception
{
JsonParser p = createParser(JSON_F, readMode, "[\"text\"]");
assertToken(JsonToken.START_ARRAY, p.nextToken());
assertToken(JsonToken.VALUE_STRING, p.nextToken());
// initially location pointing to first character
assertEquals(3, p.getCurrentLocation().getColumnNr());
p.finishToken();
// but will move once we force reading
assertEquals(8, p.getCurrentLocation().getColumnNr());
// and no change if we call again (but is ok to call)
p.finishToken();
assertEquals(8, p.getCurrentLocation().getColumnNr());

// also just for fun, verify content
assertEquals("text", p.getText());
assertEquals(8, p.getCurrentLocation().getColumnNr());
p.close();
}

// for [core#533]
public void testUtf8Bom() throws Exception
{
Expand Down Expand Up @@ -192,4 +234,75 @@ private byte[] withUtf8Bom(byte[] bytes) {
System.arraycopy(bytes, 0, arr, 3, bytes.length);
return arr;
}

// [core#603]
public void testBigPayload() throws IOException {
JsonLocation loc;
JsonParser p;

String doc = "{\"key\":\"" + generateRandomAlpha(50000) + "\"}";

p = createParserUsingStream(JSON_F, doc, "UTF-8");

assertToken(JsonToken.START_OBJECT, p.nextToken());
loc = p.getTokenLocation();
assertEquals(0, loc.getByteOffset());
assertEquals(-1L, loc.getCharOffset());
assertEquals(1, loc.getLineNr());
assertEquals(1, loc.getColumnNr());
loc = p.getCurrentLocation();
assertEquals(1, loc.getByteOffset());
assertEquals(-1L, loc.getCharOffset());
assertEquals(1, loc.getLineNr());
assertEquals(2, loc.getColumnNr());

assertToken(JsonToken.FIELD_NAME, p.nextToken());
loc = p.getTokenLocation();
assertEquals(1, loc.getByteOffset());
assertEquals(-1L, loc.getCharOffset());
assertEquals(1, loc.getLineNr());
assertEquals(2, loc.getColumnNr());
loc = p.getCurrentLocation();
assertEquals(8, loc.getByteOffset());
assertEquals(-1L, loc.getCharOffset());
assertEquals(1, loc.getLineNr());
assertEquals(9, loc.getColumnNr());

assertToken(JsonToken.VALUE_STRING, p.nextToken());
loc = p.getTokenLocation();
assertEquals(7, loc.getByteOffset());
assertEquals(-1L, loc.getCharOffset());
assertEquals(1, loc.getLineNr());
assertEquals(8, loc.getColumnNr());
loc = p.getCurrentLocation();
assertEquals(8, loc.getByteOffset());
assertEquals(-1L, loc.getCharOffset());
assertEquals(1, loc.getLineNr());
assertEquals(9, loc.getColumnNr());

p.getTextCharacters();
loc = p.getTokenLocation();
assertEquals(7, loc.getByteOffset());
assertEquals(-1L, loc.getCharOffset());
assertEquals(1, loc.getLineNr());
assertEquals(8, loc.getColumnNr());
loc = p.getCurrentLocation();
assertEquals(doc.length() - 1, loc.getByteOffset());
assertEquals(-1L, loc.getCharOffset());
assertEquals(1, loc.getLineNr());
assertEquals(doc.length(), loc.getColumnNr());

p.close();
}

private String generateRandomAlpha(int length) {
StringBuilder sb = new StringBuilder(length);
Random rnd = new Random(length);
for (int i = 0; i < length; ++i) {
// let's limit it not to include surrogate pairs:
char ch = (char) ('A' + rnd.nextInt(26));
sb.append(ch);
}
return sb.toString();
}
}

0 comments on commit 18819b1

Please sign in to comment.