When input ends in the middle of a root-level value, the Smile non-blocking parser (NonBlockingByteArrayParser) does not report an error: after endOfInput(), nextToken() returns null and the parser closes cleanly, so the truncated value is silently dropped.
The blocking SmileParser reports JsonEOFException for the same input, and the non-blocking parser itself does report EOF correctly when the truncated value is inside an Array or Object.
Reproduction
SmileFactory f = new SmileFactory();
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
try (JsonGenerator g = f.createGenerator(bytes)) {
g.writeBinary(new byte[300]); // same with a long String
}
byte[] doc = Arrays.copyOf(bytes.toByteArray(), bytes.size() - 5); // truncate
try (JsonParser p = f.createNonBlockingByteArrayParser()) {
ByteArrayFeeder feeder = (ByteArrayFeeder) p.getNonBlockingInputFeeder();
feeder.feedInput(doc, 0, doc.length);
p.nextToken(); // NOT_AVAILABLE
feeder.endOfInput();
p.nextToken(); // null; p.isClosed() == true -- no exception
}
Observed (2.18 branch):
| Case |
Result |
| Async, root-level value truncated (binary or String) |
nextToken() returns null, no exception |
Async, same value truncated inside [ ... ] |
JsonEOFException: Unexpected end-of-input: expected close marker for Array |
| Blocking, root-level value truncated |
JsonEOFException: Unexpected end-of-input for Binary value (7-bit): expected 300 payload bytes ... |
Cause
NonBlockingParserBase._eofAsNextToken() only reports an error for open Array/Object scopes. At root level, a partially-decoded token (current token NOT_AVAILABLE, mid-value minor state) is not considered.
Suggested fix
In nextToken()'s _endOfInput branch, report invalid EOF when the current token is NOT_AVAILABLE (i.e. a token was in progress), similar to what jackson-core's non-blocking JSON parser does in _finishTokenWithEOF().
Found while reviewing #826.
When input ends in the middle of a root-level value, the Smile non-blocking parser (
NonBlockingByteArrayParser) does not report an error: afterendOfInput(),nextToken()returnsnulland the parser closes cleanly, so the truncated value is silently dropped.The blocking
SmileParserreportsJsonEOFExceptionfor the same input, and the non-blocking parser itself does report EOF correctly when the truncated value is inside an Array or Object.Reproduction
Observed (2.18 branch):
nextToken()returnsnull, no exception[ ... ]JsonEOFException: Unexpected end-of-input: expected close marker for ArrayJsonEOFException: Unexpected end-of-input for Binary value (7-bit): expected 300 payload bytes ...Cause
NonBlockingParserBase._eofAsNextToken()only reports an error for open Array/Object scopes. At root level, a partially-decoded token (current tokenNOT_AVAILABLE, mid-value minor state) is not considered.Suggested fix
In
nextToken()'s_endOfInputbranch, report invalid EOF when the current token isNOT_AVAILABLE(i.e. a token was in progress), similar to what jackson-core's non-blocking JSON parser does in_finishTokenWithEOF().Found while reviewing #826.