Program: 156160
Project: 156160
Buggy source:
@Override protected Object decode(Channel channel,SocketAddress remoteAddress,Object msg) throws Exception {
  ChannelBuffer buf=(ChannelBuffer)msg;
  buf.readUnsignedByte();
  int length=(buf.readUnsignedShort() & 0x7fff) + 3;
  List<Position> positions=new LinkedList<>();
  Set<Integer> tags=new HashSet<>();
  boolean hasLocation=false;
  Position position=new Position();
  position.setProtocol(getProtocolName());
  while (buf.readerIndex() < length) {
    int tag=buf.readUnsignedByte();
    if (tags.contains(tag)) {
      if (hasLocation && position.getFixTime() != null) {
        positions.add(position);
      }
      tags.clear();
      hasLocation=false;
      position=new Position();
    }
    tags.add(tag);
switch (tag) {
case TAG_IMEI:
      String imei=buf.toString(buf.readerIndex(),15,Charset.defaultCharset());
    buf.skipBytes(imei.length());
  identify(imei,channel);
break;
case TAG_DATE:
position.setTime(new Date(buf.readUnsignedInt() * 1000));
break;
case TAG_COORDINATES:
hasLocation=true;
position.setValid((buf.readUnsignedByte() & 0xf0) == 0x00);
position.setLatitude(buf.readInt() / 1000000.0);
position.setLongitude(buf.readInt() / 1000000.0);
break;
case TAG_SPEED_COURSE:
position.setSpeed(buf.readUnsignedShort() * 0.0539957);
position.setCourse(buf.readUnsignedShort() * 0.1);
break;
case TAG_ALTITUDE:
position.setAltitude(buf.readShort());
break;
case TAG_STATUS:
int status=buf.readUnsignedShort();
position.set(Event.KEY_IGNITION,BitUtil.check(status,9));
position.set(Event.KEY_ALARM,BitUtil.check(status,15));
position.set(Event.KEY_POWER,BitUtil.check(status,2));
break;
case TAG_DIGITAL_INPUTS:
int input=buf.readUnsignedShort();
for (int i=0; i < 16; i++) position.set(Event.PREFIX_IO + (i + 1),BitUtil.check(input,i));
break;
case TAG_DIGITAL_OUTPUTS:
int output=buf.readUnsignedShort();
for (int i=0; i < 16; i++) position.set(Event.PREFIX_IO + (i + 17),BitUtil.check(output,i));
break;
case TAG_INPUT_VOLTAGE1:
position.set(Event.PREFIX_ADC + 1,buf.readUnsignedShort() / 1000.0);
break;
case TAG_INPUT_VOLTAGE2:
position.set(Event.PREFIX_ADC + 2,buf.readUnsignedShort() / 1000.0);
break;
case TAG_INPUT_VOLTAGE3:
position.set(Event.PREFIX_ADC + 3,buf.readUnsignedShort() / 1000.0);
break;
case TAG_INPUT_VOLTAGE4:
position.set(Event.PREFIX_ADC + 4,buf.readUnsignedShort() / 1000.0);
break;
case TAG_XT1:
case TAG_XT2:
case TAG_XT3:
buf.skipBytes(16);
break;
default :
break;
}
}
if (hasLocation && position.getFixTime() != null) {
positions.add(position);
}
if (!hasDeviceId()) {
Log.warning("String_Node_Str");
return null;
}
sendReply(channel,buf.readUnsignedShort());
for (Position p : positions) {
p.setDeviceId(getDeviceId());
}
if (positions.isEmpty()) {
return null;
}
return positions;
}

Fixed version (ground truth):
@Override protected Object decode(Channel channel,SocketAddress remoteAddress,Object msg) throws Exception {
  ChannelBuffer buf=(ChannelBuffer)msg;
  buf.readUnsignedByte();
  int length=(buf.readUnsignedShort() & 0x7fff) + 3;
  List<Position> positions=new LinkedList<>();
  Set<Integer> tags=new HashSet<>();
  boolean hasLocation=false;
  Position position=new Position();
  position.setProtocol(getProtocolName());
  while (buf.readerIndex() < length) {
    int tag=buf.readUnsignedByte();
    if (tags.contains(tag)) {
      if (hasLocation && position.getFixTime() != null) {
        positions.add(position);
      }
      tags.clear();
      hasLocation=false;
      position=new Position();
    }
    tags.add(tag);
switch (tag) {
case TAG_IMEI:
      String imei=buf.toString(buf.readerIndex(),15,Charset.defaultCharset());
    buf.skipBytes(imei.length());
  identify(imei,channel);
break;
case TAG_DATE:
position.setTime(new Date(buf.readUnsignedInt() * 1000));
break;
case TAG_COORDINATES:
hasLocation=true;
position.setValid((buf.readUnsignedByte() & 0xf0) == 0x00);
position.setLatitude(buf.readInt() / 1000000.0);
position.setLongitude(buf.readInt() / 1000000.0);
break;
case TAG_SPEED_COURSE:
position.setSpeed(buf.readUnsignedShort() * 0.0539957);
position.setCourse(buf.readUnsignedShort() * 0.1);
break;
case TAG_ALTITUDE:
position.setAltitude(buf.readShort());
break;
case TAG_STATUS:
int status=buf.readUnsignedShort();
position.set(Event.KEY_IGNITION,BitUtil.check(status,9));
position.set(Event.KEY_ALARM,BitUtil.check(status,15));
position.set(Event.KEY_POWER,BitUtil.check(status,2));
break;
case TAG_DIGITAL_INPUTS:
int input=buf.readUnsignedShort();
for (int i=0; i < 16; i++) {
position.set(Event.PREFIX_IO + (i + 1),BitUtil.check(input,i));
}
break;
case TAG_DIGITAL_OUTPUTS:
int output=buf.readUnsignedShort();
for (int i=0; i < 16; i++) {
position.set(Event.PREFIX_IO + (i + 17),BitUtil.check(output,i));
}
break;
case TAG_INPUT_VOLTAGE1:
position.set(Event.PREFIX_ADC + 1,buf.readUnsignedShort() / 1000.0);
break;
case TAG_INPUT_VOLTAGE2:
position.set(Event.PREFIX_ADC + 2,buf.readUnsignedShort() / 1000.0);
break;
case TAG_INPUT_VOLTAGE3:
position.set(Event.PREFIX_ADC + 3,buf.readUnsignedShort() / 1000.0);
break;
case TAG_INPUT_VOLTAGE4:
position.set(Event.PREFIX_ADC + 4,buf.readUnsignedShort() / 1000.0);
break;
case TAG_XT1:
case TAG_XT2:
case TAG_XT3:
buf.skipBytes(16);
break;
default :
break;
}
}
if (hasLocation && position.getFixTime() != null) {
positions.add(position);
}
if (!hasDeviceId()) {
Log.warning("String_Node_Str");
return null;
}
sendReply(channel,buf.readUnsignedShort());
for (Position p : positions) {
p.setDeviceId(getDeviceId());
}
if (positions.isEmpty()) {
return null;
}
return positions;
}