Program: 45345
Project: 45345
Buggy source:
/** 
 * Create a text node for the contents of a CDATA element like style or script which ends with &lt;/foo> for some foo.
 * @param container container node
 * @return cdata node
 */
public Node getCDATA(Node container){
  int c, lastc, start, len, i;
  int qt=0;
  int esc=0;
  String str;
  boolean endtag=false;
  boolean begtag=false;
  if (container.isJavaScript()) {
    esc='\\';
  }
  this.lines=this.in.getCurline();
  this.columns=this.in.getCurcol();
  this.waswhite=false;
  this.txtstart=this.lexsize;
  this.txtend=this.lexsize;
  lastc='\0';
  start=-1;
  while ((c=this.in.readChar()) != StreamIn.END_OF_STREAM) {
    if (qt > 0) {
      if ((c == '\r' || c == '\n' || c == qt) && (!TidyUtils.toBoolean(esc) || lastc != esc)) {
        qt=0;
      }
 else       if (c == '/' && lastc == '<') {
        start=this.lexsize + 1;
      }
 else       if (c == '>' && start >= 0) {
        len=this.lexsize - start;
        this.lines=this.in.getCurline();
        this.columns=this.in.getCurcol() - 3;
        report.warning(this,null,null,Report.BAD_CDATA_CONTENT);
        if (TidyUtils.toBoolean(esc)) {
          for (i=this.lexsize; i > start - 1; --i) {
            this.lexbuf[i]=this.lexbuf[i - 1];
          }
          this.lexbuf[start - 1]=(byte)esc;
          this.lexsize++;
        }
        start=-1;
      }
    }
 else     if (TidyUtils.isQuote(c) && (!TidyUtils.toBoolean(esc) || lastc != esc)) {
      qt=c;
    }
 else     if (c == '<') {
      start=this.lexsize + 1;
      endtag=false;
      begtag=true;
    }
 else     if (c == '!' && lastc == '<') {
      start=-1;
      endtag=false;
      begtag=false;
    }
 else     if (c == '/' && lastc == '<') {
      start=this.lexsize + 1;
      endtag=true;
      begtag=false;
    }
 else     if (c == '>' && start >= 0) {
      int decr=2;
      if (endtag && ((len=this.lexsize - start) == container.element.length())) {
        str=TidyUtils.getString(this.lexbuf,start,len);
        if (container.element.equalsIgnoreCase(str)) {
          this.txtend=start - decr;
          this.lexsize=start - decr;
          break;
        }
      }
      this.lines=this.in.getCurline();
      this.columns=this.in.getCurcol() - 3;
      report.warning(this,null,null,Report.BAD_CDATA_CONTENT);
      if (begtag) {
        decr=1;
      }
      this.txtend=start - decr;
      this.lexsize=start - decr;
      break;
    }
 else     if (c == '\r') {
      if (begtag || endtag) {
        continue;
      }
      c=this.in.readChar();
      if (c != '\n') {
        this.in.ungetChar(c);
      }
      c='\n';
    }
 else     if ((c == '\n' || c == '\t' || c == ' ') && (begtag || endtag)) {
      continue;
    }
    addCharToLexer(c);
    this.txtend=this.lexsize;
    lastc=c;
  }
  if (c == StreamIn.END_OF_STREAM) {
    report.warning(this,container,null,Report.MISSING_ENDTAG_FOR);
  }
  if (this.txtend > this.txtstart) {
    this.token=newNode(NodeType.TextNode,this.lexbuf,this.txtstart,this.txtend);
    return this.token;
  }
  return null;
}

Fixed version (ground truth):
/** 
 * Create a text node for the contents of a CDATA element like style or script which ends with &lt;/foo> for some foo.
 * @param container container node
 * @return cdata node
 */
public Node getCDATA(Node container){
  int start=0;
  int nested=0;
  CDataState state=CDataState.INTERMEDIATE;
  int c;
  boolean isEmpty=true;
  boolean matches=false;
  boolean hasSrc=container.getAttrById(AttrId.SRC) != null;
  this.lines=this.in.getCurline();
  this.columns=this.in.getCurcol();
  this.waswhite=false;
  this.txtstart=this.lexsize;
  this.txtend=this.lexsize;
  while ((c=this.in.readChar()) != StreamIn.END_OF_STREAM) {
    addCharToLexer(c);
    txtend=lexsize;
    if (state == CDataState.INTERMEDIATE) {
      if (c != '<') {
        if (isEmpty && !TidyUtils.isWhite((char)c)) {
          isEmpty=false;
        }
        continue;
      }
      c=in.readChar();
      if (TidyUtils.isLetter((char)c)) {
        if (hasSrc && isEmpty && container.is(TagId.SCRIPT)) {
          lexsize=txtstart;
          in.ungetChar(c);
          in.ungetChar('<');
          return null;
        }
        addCharToLexer(c);
        start=lexsize - 1;
        state=CDataState.STARTTAG;
      }
 else       if (c == '/') {
        addCharToLexer(c);
        c=in.readChar();
        if (!TidyUtils.isLetter((char)c)) {
          in.ungetChar(c);
          continue;
        }
        in.ungetChar(c);
        start=lexsize;
        state=CDataState.ENDTAG;
      }
 else       if (c == '\\') {
        addCharToLexer(c);
        c=in.readChar();
        if (c != '/') {
          in.ungetChar(c);
          continue;
        }
        addCharToLexer(c);
        c=in.readChar();
        if (!TidyUtils.isLetter((char)c)) {
          in.ungetChar(c);
          continue;
        }
        in.ungetChar(c);
        start=lexsize;
        state=CDataState.ENDTAG;
      }
 else {
        in.ungetChar(c);
      }
    }
 else     if (state == CDataState.STARTTAG) {
      if (TidyUtils.isLetter((char)c)) {
        continue;
      }
      matches=container.element.equalsIgnoreCase(TidyUtils.getString(lexbuf,start,container.element.length()));
      if (matches) {
        nested++;
      }
      state=CDataState.INTERMEDIATE;
    }
 else     if (state == CDataState.ENDTAG) {
      if (TidyUtils.isLetter((char)c)) {
        continue;
      }
      matches=container.element.equalsIgnoreCase(TidyUtils.getString(lexbuf,start,container.element.length()));
      if (isEmpty && !matches) {
        for (int i=lexsize - 1; i >= start; --i) {
          in.ungetChar(lexbuf[i]);
        }
        in.ungetChar('/');
        in.ungetChar('<');
        break;
      }
      if (matches && nested-- <= 0) {
        for (int i=lexsize - 1; i >= start; --i) {
          in.ungetChar(lexbuf[i]);
        }
        in.ungetChar('/');
        in.ungetChar('<');
        lexsize-=(lexsize - start) + 2;
        break;
      }
 else       if (lexbuf[start - 2] != '\\') {
        lines=in.getCurline();
        columns=in.getCurcol();
        columns-=3;
        report.error(this,null,null,Report.BAD_CDATA_CONTENT);
        if (container.isJavaScript()) {
          for (int i=lexsize; i > start - 1; --i) {
            lexbuf[i]=lexbuf[i - 1];
          }
          lexbuf[start - 1]='\\';
          lexsize++;
        }
      }
      state=CDataState.INTERMEDIATE;
    }
  }
  if (isEmpty) {
    lexsize=txtstart=txtend;
  }
 else {
    txtend=lexsize;
  }
  if (c == StreamIn.END_OF_STREAM) {
    report.error(this,container,null,Report.MISSING_ENDTAG_FOR);
  }
  return newNode(NodeType.TextNode,lexbuf,txtstart,txtend);
}