Program: 63812
Project: 63812
Buggy source:
public int read(ByteBuffer outBuf) throws IOException {
  int len=outBuf.remaining();
  if (len == 0) {
    return 0;
  }
  if (len % 8 != 0) {
    throw new Error("String_Node_Str");
  }
  int outPtr=outBuf.position();
  int outEnd=outPtr + len;
  ByteBuffer inBuf=this.inner.getReadBuffer();
  while (true) {
    byte tag=0;
    if (inBuf.remaining() < 10) {
      if (outBuf.remaining() == 0) {
        return len;
      }
      if (inBuf.remaining() == 0) {
        inBuf=this.inner.getReadBuffer();
        continue;
      }
      tag=inBuf.get();
      for (int i=0; i < 8; ++i) {
        if ((tag & (1 << i)) != 0) {
          if (inBuf.remaining() == 0) {
            inBuf=this.inner.getReadBuffer();
          }
          outBuf.put(inBuf.get());
        }
 else {
          outBuf.put((byte)0);
        }
      }
      if (inBuf.remaining() == 0 && (tag == 0 || tag == (byte)0xff)) {
        inBuf=this.inner.getReadBuffer();
      }
    }
 else {
      tag=inBuf.get();
      for (int n=0; n < 8; ++n) {
        boolean isNonzero=(tag & (1 << n)) != 0;
        outBuf.put((byte)(inBuf.get() & (isNonzero ? -1 : 0)));
        inBuf.position(inBuf.position() + (isNonzero ? 0 : -1));
      }
    }
    if (tag == 0) {
      if (inBuf.remaining() == 0) {
        throw new Error("String_Node_Str");
      }
      int runLength=inBuf.get() * 8;
      if (runLength > outEnd - outPtr) {
        throw new Error("String_Node_Str");
      }
      for (int i=0; i < runLength; ++i) {
        outBuf.put((byte)0);
      }
    }
 else     if (tag == (byte)0xff) {
      int runLength=inBuf.get() * 8;
      if (inBuf.remaining() >= runLength) {
        ByteBuffer slice=inBuf.slice();
        slice.limit(runLength);
        outBuf.put(slice);
        inBuf.position(inBuf.position() + runLength);
      }
 else {
        runLength-=inBuf.remaining();
        outBuf.put(inBuf);
        ByteBuffer slice=outBuf.slice();
        slice.limit(runLength);
        this.inner.read(slice);
        outBuf.position(outBuf.position() + runLength);
        if (outBuf.remaining() == 0) {
          return len;
        }
 else {
          inBuf=this.inner.getReadBuffer();
          continue;
        }
      }
    }
    if (outBuf.remaining() == 0) {
      return len;
    }
  }
}

Fixed version (ground truth):
public int read(ByteBuffer outBuf) throws IOException {
  int len=outBuf.remaining();
  if (len == 0) {
    return 0;
  }
  if (len % 8 != 0) {
    throw new Error("String_Node_Str");
  }
  int outPtr=outBuf.position();
  int outEnd=outPtr + len;
  ByteBuffer inBuf=this.inner.getReadBuffer();
  while (true) {
    byte tag=0;
    if (inBuf.remaining() < 10) {
      if (outBuf.remaining() == 0) {
        return len;
      }
      if (inBuf.remaining() == 0) {
        inBuf=this.inner.getReadBuffer();
        continue;
      }
      tag=inBuf.get();
      for (int i=0; i < 8; ++i) {
        if ((tag & (1 << i)) != 0) {
          if (inBuf.remaining() == 0) {
            inBuf=this.inner.getReadBuffer();
          }
          outBuf.put(inBuf.get());
        }
 else {
          outBuf.put((byte)0);
        }
      }
      if (inBuf.remaining() == 0 && (tag == 0 || tag == (byte)0xff)) {
        inBuf=this.inner.getReadBuffer();
      }
    }
 else {
      tag=inBuf.get();
      for (int n=0; n < 8; ++n) {
        boolean isNonzero=(tag & (1 << n)) != 0;
        outBuf.put((byte)(inBuf.get() & (isNonzero ? -1 : 0)));
        inBuf.position(inBuf.position() + (isNonzero ? 0 : -1));
      }
    }
    if (tag == 0) {
      if (inBuf.remaining() == 0) {
        throw new Error("String_Node_Str");
      }
      int runLength=(0xff & (int)inBuf.get()) * 8;
      if (runLength > outEnd - outPtr) {
        throw new Error("String_Node_Str");
      }
      for (int i=0; i < runLength; ++i) {
        outBuf.put((byte)0);
      }
    }
 else     if (tag == (byte)0xff) {
      int runLength=(0xff & (int)inBuf.get()) * 8;
      if (inBuf.remaining() >= runLength) {
        ByteBuffer slice=inBuf.slice();
        slice.limit(runLength);
        outBuf.put(slice);
        inBuf.position(inBuf.position() + runLength);
      }
 else {
        runLength-=inBuf.remaining();
        outBuf.put(inBuf);
        ByteBuffer slice=outBuf.slice();
        slice.limit(runLength);
        this.inner.read(slice);
        outBuf.position(outBuf.position() + runLength);
        if (outBuf.remaining() == 0) {
          return len;
        }
 else {
          inBuf=this.inner.getReadBuffer();
          continue;
        }
      }
    }
    if (outBuf.remaining() == 0) {
      return len;
    }
  }
}