Program: 63427
Project: 63427
Buggy source:
/** 
 * This method cannot move the buffer position until a message is found or an error has occurred. Otherwise, MINA will compact the buffer and we lose data.
 */
private boolean parseMessage(ByteBuffer in,ProtocolDecoderOutput out) throws ProtocolCodecException {
  try {
    boolean messageFound=false;
    while (in.hasRemaining() && !messageFound) {
      if (state == SEEKING_HEADER) {
        BufPos bufPos=indexOf(in,position,HEADER_PATTERN);
        int headerOffset=bufPos._offset;
        if (headerOffset == -1) {
          break;
        }
        in.position(headerOffset);
        if (log.isDebugEnabled()) {
          log.debug("String_Node_Str" + getBufferDebugInfo(in));
        }
        position=headerOffset + bufPos._length;
        state=PARSING_LENGTH;
      }
      if (state == PARSING_LENGTH) {
        byte ch=0;
        while (hasRemaining(in)) {
          ch=get(in);
          if (!Character.isDigit((char)ch)) {
            break;
          }
          bodyLength=bodyLength * 10 + (ch - '0');
        }
        if (ch == '\001') {
          state=READING_BODY;
          if (log.isDebugEnabled()) {
            log.debug("String_Node_Str" + bodyLength + "String_Node_Str"+ getBufferDebugInfo(in));
          }
        }
 else {
          if (hasRemaining(in)) {
            handleError(in,in.position() + 1,"String_Node_Str",false);
            continue;
          }
 else {
            break;
          }
        }
      }
      if (state == READING_BODY) {
        if (remaining(in) < bodyLength) {
          break;
        }
        position+=bodyLength;
        state=PARSING_CHECKSUM;
        if (log.isDebugEnabled()) {
          log.debug("String_Node_Str" + getBufferDebugInfo(in));
        }
      }
      if (state == PARSING_CHECKSUM) {
        if (startsWith(in,position,CHECKSUM_PATTERN) > 0) {
          if (log.isDebugEnabled()) {
            log.debug("String_Node_Str" + getBufferDebugInfo(in));
          }
          position+=CHECKSUM_PATTERN.length;
        }
 else {
          if (position + CHECKSUM_PATTERN.length <= in.limit()) {
            int recoveryPosition=position + 1;
            handleError(in,recoveryPosition,"String_Node_Str",isLogon(in));
            continue;
          }
 else {
            break;
          }
        }
        String messageString=getMessageString(in);
        if (log.isDebugEnabled()) {
          log.debug("String_Node_Str" + getBufferDebugInfo(in) + "String_Node_Str"+ messageString);
        }
        out.write(messageString);
        state=SEEKING_HEADER;
        bodyLength=0;
        messageFound=true;
      }
    }
    return messageFound;
  }
 catch (  Throwable t) {
    state=SEEKING_HEADER;
    position=0;
    bodyLength=0;
    if (t instanceof ProtocolCodecException) {
      throw (ProtocolCodecException)t;
    }
 else {
      throw new ProtocolCodecException(t);
    }
  }
}

Fixed version (ground truth):
/** 
 * This method cannot move the buffer position until a message is found or an error has occurred. Otherwise, MINA will compact the buffer and we lose data.
 */
private boolean parseMessage(ByteBuffer in,ProtocolDecoderOutput out) throws ProtocolCodecException {
  try {
    boolean messageFound=false;
    while (in.hasRemaining() && !messageFound) {
      if (state == SEEKING_HEADER) {
        BufPos bufPos=indexOf(in,position,HEADER_PATTERN);
        int headerOffset=bufPos._offset;
        if (headerOffset == -1) {
          break;
        }
        in.position(headerOffset);
        if (log.isDebugEnabled()) {
          log.debug("String_Node_Str" + getBufferDebugInfo(in));
        }
        position=headerOffset + bufPos._length;
        state=PARSING_LENGTH;
      }
      if (state == PARSING_LENGTH) {
        byte ch=0;
        while (hasRemaining(in)) {
          ch=get(in);
          if (!Character.isDigit((char)ch)) {
            break;
          }
          bodyLength=bodyLength * 10 + (ch - '0');
        }
        if (ch == '\001') {
          state=READING_BODY;
          if (log.isDebugEnabled()) {
            log.debug("String_Node_Str" + bodyLength + "String_Node_Str"+ getBufferDebugInfo(in));
          }
        }
 else {
          if (hasRemaining(in)) {
            String messageString=getMessageStringForError(in);
            handleError(in,in.position() + 1,"String_Node_Str" + ch + "String_Node_Str"+ messageString,false);
            continue;
          }
 else {
            break;
          }
        }
      }
      if (state == READING_BODY) {
        if (remaining(in) < bodyLength) {
          break;
        }
        position+=bodyLength;
        state=PARSING_CHECKSUM;
        if (log.isDebugEnabled()) {
          log.debug("String_Node_Str" + getBufferDebugInfo(in));
        }
      }
      if (state == PARSING_CHECKSUM) {
        if (startsWith(in,position,CHECKSUM_PATTERN) > 0) {
          if (log.isDebugEnabled()) {
            log.debug("String_Node_Str" + getBufferDebugInfo(in));
          }
          position+=CHECKSUM_PATTERN.length;
        }
 else {
          if (position + CHECKSUM_PATTERN.length <= in.limit()) {
            int recoveryPosition=position + 1;
            handleError(in,recoveryPosition,"String_Node_Str",isLogon(in));
            continue;
          }
 else {
            break;
          }
        }
        String messageString=getMessageString(in);
        if (log.isDebugEnabled()) {
          log.debug("String_Node_Str" + getBufferDebugInfo(in) + "String_Node_Str"+ messageString);
        }
        out.write(messageString);
        state=SEEKING_HEADER;
        bodyLength=0;
        messageFound=true;
      }
    }
    return messageFound;
  }
 catch (  Throwable t) {
    state=SEEKING_HEADER;
    position=0;
    bodyLength=0;
    if (t instanceof ProtocolCodecException) {
      throw (ProtocolCodecException)t;
    }
 else {
      throw new ProtocolCodecException(t);
    }
  }
}