Buggy code:
private int sizeOfLastChunk ; private int [ ] chunkOffsets ; private int documentReferenceSize ; private int startOfCategoryTables ; private HashtableOfIntValues categoryOffsets ; private HashtableOfIntValues categoryEnds ; private int cacheUserCount ; private String [ ] [ ] cachedChunks ; private HashtableOfObject categoryTables ; private char [ ] cachedCategoryName ; private static final int DEFAULT_BUFFER_SIZE = 2048 ; private static int BUFFER_READ_SIZE = DiskIndex . DEFAULT_BUFFER_SIZE ; private static final int BUFFER_WRITE_SIZE = DiskIndex . DEFAULT_BUFFER_SIZE ; private byte [ ] streamBuffer ; private int bufferIndex ; private int bufferEnd ; private int streamEnd ; public static final String SIGNATURE = "INDEX<seq2seq4repair_space>VERSION<seq2seq4repair_space>1.121" ; private static final char [ ] SIGNATURE_CHARS = DiskIndex . SIGNATURE . toCharArray ( ) ; public static boolean DEBUG = false ; private static final int RE_INDEXED = - 1 ; private static final int DELETED = - 2 ; private static final int CHUNK_SIZE = 100 ; private static final SimpleSetOfCharArray INTERNED_CATEGORY_NAMES = new SimpleSetOfCharArray ( 20 ) ; static class IntList { int size ; int [ ] elements ; IntList ( int [ ] elements ) { } void add ( int newElement ) { } int [ ] asArray ( ) { } } DiskIndex ( String fileName ) { } SimpleSet addDocumentNames ( String substring , MemoryIndex memoryIndex ) throws IOException { } private HashtableOfObject addQueryResult ( HashtableOfObject results , char [ ] word , HashtableOfObject wordsToDocNumbers , MemoryIndex memoryIndex ) throws IOException { } HashtableOfObject addQueryResults ( char [ ] [ ] categories , char [ ] key , int matchRule , MemoryIndex memoryIndex ) throws IOException { } private void cacheDocumentNames ( ) throws IOException { } private String [ ] computeDocumentNames ( String [ ] onDiskNames , int [ ] positions , SimpleLookupTable indexedDocuments , MemoryIndex memoryIndex ) { } private void copyQueryResults ( HashtableOfObject categoryToWords , int newPosition ) { } void initialize ( boolean reuseExistingFile ) throws IOException { } private void initializeFrom ( DiskIndex diskIndex , File newIndexFile ) throws IOException { } private void mergeCategories ( DiskIndex onDisk , int [ ] positions , FileOutputStream stream ) throws IOException { } private void mergeCategory ( char [ ] categoryName , DiskIndex onDisk , int [ ] positions , FileOutputStream stream ) throws IOException { } DiskIndex mergeWith ( MemoryIndex memoryIndex ) throws IOException { } private synchronized String [ ] readAllDocumentNames ( ) throws IOException { } private synchronized HashtableOfObject readCategoryTable ( char [ ] categoryName , boolean readDocNumbers ) throws IOException { } private void readChunk ( String [ ] docNames , FileInputStream stream , int index , int size ) throws IOException { } synchronized String readDocumentName ( int docNumber ) throws IOException { } synchronized int [ ] readDocumentNumbers ( Object arrayOffset ) throws IOException { } private void readHeaderInfo ( RandomAccessFile file ) throws IOException { } synchronized void startQuery ( ) { } synchronized void stopQuery ( ) { } private void readStreamBuffer ( FileInputStream stream ) throws IOException { } private char [ ] readStreamChars ( FileInputStream stream ) throws IOException { if ( ( stream != null ) && ( ( ( this . bufferIndex ) + 2 ) >= ( this . bufferEnd ) ) ) readStreamBuffer ( stream ) ; int length = ( ( streamBuffer [ ( ( this . bufferIndex ) ++ ) ] ) & 255 ) << 8 ; length += ( this . streamBuffer [ ( ( this . bufferIndex ) ++ ) ] ) & 255 ; char [ ] word = new char [ length ] ; int i = 0 ; while ( i < length ) { int charsInBuffer = i + ( ( ( this . bufferEnd ) - ( this . bufferIndex ) ) // 3 ) ; <START_BUG> if ( ( charsInBuffer > length ) || ( ( this . bufferEnd ) != ( this . streamBuffer . length ) ) ) <END_BUG> charsInBuffer = length ; while ( i < charsInBuffer ) { byte b = this . streamBuffer [ ( ( this . bufferIndex ) ++ ) ] ; switch ( b & 240 ) { case 0 : case 16 : case 32 : case 48 : case 64 : case 80 : case 96 : case 112 : word [ ( i ++ ) ] = ( ( char ) ( b ) ) ; break ; case 192 : case 208 : char next = ( ( char ) ( this . streamBuffer [ ( ( this . bufferIndex ) ++ ) ] ) ) ; if ( ( next & 192 ) != 128 ) { throw new UTFDataFormatException ( ) ; } char ch = ( ( char ) ( ( b & 31 ) << 6 ) ) ; ch |= next & 63 ; word [ ( i ++ ) ] = ch ; break ; case 224 : char first = ( ( char ) ( this . streamBuffer [ ( ( this . bufferIndex ) ++ ) ] ) ) ; char second = ( ( char ) ( this . streamBuffer [ ( ( this . bufferIndex ) ++ ) ] ) ) ; if ( ( ( first & second ) & 192 ) != 128 ) { throw new UTFDataFormatException ( ) ; } ch = ( ( char ) ( ( b & 15 ) << 12 ) ) ; ch |= ( first & 63 ) << 6 ; ch |= second & 63 ; word [ ( i ++ ) ] = ch ; break ; default : throw new UTFDataFormatException ( ) ; } } if ( ( i < length ) && ( stream != null ) ) readStreamBuffer ( stream ) ; } return word ; } private int [ ] readStreamDocumentArray ( FileInputStream stream , int arraySize ) throws IOException { } private int readStreamInt ( FileInputStream stream ) throws IOException { }

Fix:
if ( ( ( charsInBuffer > length ) || ( ( this . bufferEnd ) != ( this . streamBuffer . length ) ) ) || ( stream == null ) )