@@ -25,6 +25,16 @@ public final class UTF8Reader
2525
2626 private byte [] _inputBuffer ;
2727
28+ /**
29+ * Flag set to indicate {@code inputBuffer} is read-only, and its
30+ * content should not be modified. This is the case when caller
31+ * has passed in a buffer of contents already read, instead of Jackson
32+ * allocating read buffer.
33+ *
34+ * @since 2.19
35+ */
36+ private final boolean _inputBufferReadOnly ;
37+
2838 /**
2939 * Pointer to the next available byte (if any), iff less than
3040 * <code>mByteBufferEnd</code>
@@ -73,7 +83,10 @@ public UTF8Reader(IOContext ctxt, InputStream in, boolean autoClose,
7383 _inputBuffer = buf ;
7484 _inputPtr = ptr ;
7585 _inputEnd = ptr +len ;
76- _autoClose = autoClose ;
86+ _autoClose = autoClose ;
87+ // Unmodifiable if there is no stream to actually read from
88+ // (ideally caller should pass explicitly)
89+ _inputBufferReadOnly = (in == null );
7790 }
7891
7992 public UTF8Reader (IOContext ctxt , byte [] buf , int ptr , int len )
@@ -85,6 +98,8 @@ public UTF8Reader(IOContext ctxt, byte[] buf, int ptr, int len)
8598 _inputPtr = ptr ;
8699 _inputEnd = ptr +len ;
87100 _autoClose = true ;
101+ // This is the case when we have a buffer of contents already read
102+ _inputBufferReadOnly = true ;
88103 }
89104
90105 public UTF8Reader (IOContext ctxt , InputStream in , boolean autoClose )
@@ -96,15 +111,8 @@ public UTF8Reader(IOContext ctxt, InputStream in, boolean autoClose)
96111 _inputPtr = 0 ;
97112 _inputEnd = 0 ;
98113 _autoClose = autoClose ;
99- }
100-
101- /**
102- * Method that can be used to see if we can actually modify the
103- * underlying buffer. This is the case if we are managing the buffer,
104- * but not if it was just given to us.
105- */
106- protected final boolean canModifyBuffer () {
107- return (_ioContext != null );
114+ // Buffer allocated above, modifiable as needed
115+ _inputBufferReadOnly = false ;
108116 }
109117
110118 /*
@@ -400,27 +408,17 @@ private boolean loadMore(int available) throws IOException
400408 {
401409 _byteCount += (_inputEnd - available );
402410
403- // Bytes that need to be moved to the beginning of buffer?
404411 if (available > 0 ) {
412+ // Should we move bytes to the beginning of buffer?
405413 if (_inputPtr > 0 ) {
406- if (!canModifyBuffer ()) {
407- // 15-Aug-2022, tatu: Occurs (only) if we have half-decoded UTF-8
408- // characters; uncovered by:
409- //
410- // https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=50036
411- //
412- // and need to be reported as IOException
413- if (_inputSource == null ) {
414- throw new IOException (String .format (
415- "End-of-input after first %d byte(s) of a UTF-8 character: needed at least one more" ,
416- available ));
414+ // Can only do so if buffer mutable
415+ if (!_inputBufferReadOnly ) {
416+ for (int i = 0 ; i < available ; ++i ) {
417+ _inputBuffer [i ] = _inputBuffer [_inputPtr +i ];
417418 }
419+ _inputPtr = 0 ;
420+ _inputEnd = available ;
418421 }
419- for (int i = 0 ; i < available ; ++i ) {
420- _inputBuffer [i ] = _inputBuffer [_inputPtr +i ];
421- }
422- _inputPtr = 0 ;
423- _inputEnd = available ;
424422 }
425423 } else {
426424 // Ok; here we can actually reasonably expect an EOF, so let's do a separate read right away:
0 commit comments