Program: 80855
Project: 80855
Buggy source:
@Override public void update2ndStep(){
  activeComponents.forEach(Component.Instance::deactivate);
  activeComponents.clear();
  super.update2ndStep();
  int rows=size / context.get(Context.KEY_COLUMNS);
  int minRowsPerServer=(minSizePerServer + context.get(Context.KEY_COLUMNS) - 1) / context.get(Context.KEY_COLUMNS);
  int maxRowsPerServer=maxSizePerServer / context.get(Context.KEY_COLUMNS);
  List<String> servers=new ArrayList<>(playersByServer.keySet());
  Collections.sort(servers);
  int[] serverRows=new int[servers.size()];
  Arrays.fill(serverRows,minRowsPerServer);
  rows-=minRowsPerServer * servers.size();
  if (serverSeparator != null && playersByServer.size() > 1) {
    rows-=((serverSeparator.getSize() + context.get(Context.KEY_COLUMNS) - 1) / context.get(Context.KEY_COLUMNS)) * (playersByServer.size() - 1);
  }
  boolean change;
  do {
    change=false;
    for (int i=0; i < servers.size(); i++) {
      if (rows > 0 && serverRows[i] < maxRowsPerServer) {
        String server=servers.get(i);
        int serverSize=serverHeader.getSize() + playersByServer.get(server).size() * playerComponent.getSize() + (serverFooter != null ? serverFooter.getSize() : 0);
        if (min(serverSize,maxRowsPerServer) > serverRows[i] * context.get(Context.KEY_COLUMNS)) {
          serverRows[i]++;
          change=true;
          rows--;
        }
      }
    }
  }
 while (rows > 0 && change);
  int pos=0;
  for (int i=0; i < servers.size() && pos < size; i++) {
    if (serverSeparator != null && i > 0) {
      pos=((pos + context.get(Context.KEY_COLUMNS) - 1) / context.get(Context.KEY_COLUMNS)) * context.get(Context.KEY_COLUMNS);
      Component.Instance separator=serverSeparator.toInstance(context);
      separator.activate();
      separator.update1stStep();
      separator.setPosition(row + (pos / context.get(Context.KEY_COLUMNS)),column,serverSeparator.getSize());
      separator.update2ndStep();
      activeComponents.add(separator);
      pos+=serverSeparator.getSize();
    }
    String server=servers.get(i);
    pos=((pos + context.get(Context.KEY_COLUMNS) - 1) / context.get(Context.KEY_COLUMNS)) * context.get(Context.KEY_COLUMNS);
    List<Player> players=playersByServer.get(server);
    Context serverContext=context.derived().put(Context.KEY_SERVER,server).put(Context.KEY_SERVER_PLAYER_COUNT,players.size());
    Component.Instance header=serverHeader.toInstance(serverContext);
    header.activate();
    header.update1stStep();
    header.setPosition(row + (pos / context.get(Context.KEY_COLUMNS)),column,serverHeader.getSize());
    header.update2ndStep();
    activeComponents.add(header);
    pos+=serverHeader.getSize();
    int playersMaxSize=playersByServer.get(server).size() * playerComponent.getSize();
    int serverSize=min(serverRows[i] * context.get(Context.KEY_COLUMNS) - serverHeader.getSize() - (serverFooter != null ? serverFooter.getSize() : 0),playersMaxSize);
    boolean allFit=serverSize >= playersMaxSize;
    int j;
    int pos2=0;
    for (j=0; (allFit || pos2 + morePlayersComponent.getSize() < serverSize) && j < players.size(); j++) {
      Player player=players.get(j);
      Component.Instance component=playerComponent.toInstance(serverContext.derived().put(Context.KEY_PLAYER,player));
      component.activate();
      component.update1stStep();
      component.setPosition(row + ((pos + pos2) / context.get(Context.KEY_COLUMNS)),column + ((pos + pos2) % context.get(Context.KEY_COLUMNS)),playerComponent.getSize());
      component.update2ndStep();
      activeComponents.add(component);
      pos2+=playerComponent.getSize();
    }
    if (!allFit) {
      Component.Instance component=morePlayersComponent.toInstance(serverContext.derived().put(Context.KEY_OTHER_PLAYERS_COUNT,players.size() - j));
      component.activate();
      component.update1stStep();
      component.setPosition(row + ((pos + pos2) / context.get(Context.KEY_COLUMNS)),column + ((pos + pos2) % context.get(Context.KEY_COLUMNS)),morePlayersComponent.getSize());
      component.update2ndStep();
      activeComponents.add(component);
      pos2+=morePlayersComponent.getSize();
    }
    if (serverFooter != null) {
      pos+=serverSize;
      Component.Instance footer=serverFooter.toInstance(serverContext);
      footer.activate();
      footer.update1stStep();
      footer.setPosition(row + (pos / context.get(Context.KEY_COLUMNS)),column + (pos % context.get(Context.KEY_COLUMNS)),serverFooter.getSize());
      footer.update2ndStep();
      activeComponents.add(footer);
      pos+=serverFooter.getSize();
    }
 else {
      pos+=pos2;
    }
  }
}

Fixed version (ground truth):
@Override public void update2ndStep(){
  activeComponents.forEach(Component.Instance::deactivate);
  activeComponents.clear();
  super.update2ndStep();
  int rows=size / context.get(Context.KEY_COLUMNS);
  int minRowsPerServer=(minSizePerServer + context.get(Context.KEY_COLUMNS) - 1) / context.get(Context.KEY_COLUMNS);
  int maxRowsPerServer=maxSizePerServer / context.get(Context.KEY_COLUMNS);
  List<String> servers=new ArrayList<>(playersByServer.keySet());
  Collections.sort(servers);
  int[] serverRows=new int[servers.size()];
  Arrays.fill(serverRows,minRowsPerServer);
  rows-=minRowsPerServer * servers.size();
  if (serverSeparator != null && playersByServer.size() > 1) {
    rows-=((serverSeparator.getSize() + context.get(Context.KEY_COLUMNS) - 1) / context.get(Context.KEY_COLUMNS)) * (playersByServer.size() - 1);
  }
  boolean change;
  do {
    change=false;
    for (int i=0; i < servers.size(); i++) {
      if (rows > 0 && serverRows[i] < maxRowsPerServer) {
        String server=servers.get(i);
        int serverSize=serverHeader.getSize() + playersByServer.get(server).size() * playerComponent.getSize() + (serverFooter != null ? serverFooter.getSize() : 0);
        if (min(serverSize,maxRowsPerServer) > serverRows[i] * context.get(Context.KEY_COLUMNS)) {
          serverRows[i]++;
          change=true;
          rows--;
        }
      }
    }
  }
 while (rows > 0 && change);
  int pos=0;
  for (int i=0; i < servers.size() && pos < size; i++) {
    if (serverSeparator != null && i > 0) {
      pos=((pos + context.get(Context.KEY_COLUMNS) - 1) / context.get(Context.KEY_COLUMNS)) * context.get(Context.KEY_COLUMNS);
      Component.Instance separator=serverSeparator.toInstance(context);
      separator.activate();
      separator.update1stStep();
      separator.setPosition(leftMostColumn,row + (pos / context.get(Context.KEY_COLUMNS)),column,serverSeparator.getSize());
      separator.update2ndStep();
      activeComponents.add(separator);
      pos+=serverSeparator.getSize();
    }
    String server=servers.get(i);
    pos=((pos + context.get(Context.KEY_COLUMNS) - 1) / context.get(Context.KEY_COLUMNS)) * context.get(Context.KEY_COLUMNS);
    List<Player> players=playersByServer.get(server);
    Context serverContext=context.derived().put(Context.KEY_SERVER,server).put(Context.KEY_SERVER_PLAYER_COUNT,players.size());
    Component.Instance header=serverHeader.toInstance(serverContext);
    header.activate();
    header.update1stStep();
    header.setPosition(leftMostColumn,row + (pos / context.get(Context.KEY_COLUMNS)),column,serverHeader.getSize());
    header.update2ndStep();
    activeComponents.add(header);
    pos+=serverHeader.getSize();
    int playersMaxSize=playersByServer.get(server).size() * playerComponent.getSize();
    int serverSize=min(serverRows[i] * context.get(Context.KEY_COLUMNS) - serverHeader.getSize() - (serverFooter != null ? serverFooter.getSize() : 0),playersMaxSize);
    boolean allFit=serverSize >= playersMaxSize;
    int j;
    int pos2=0;
    for (j=0; (allFit || pos2 + morePlayersComponent.getSize() < serverSize) && j < players.size(); j++) {
      Player player=players.get(j);
      Component.Instance component=playerComponent.toInstance(serverContext.derived().put(Context.KEY_PLAYER,player));
      component.activate();
      component.update1stStep();
      component.setPosition(leftMostColumn,row + ((pos + pos2) / context.get(Context.KEY_COLUMNS)),leftMostColumn + ((pos + pos2) % context.get(Context.KEY_COLUMNS)),playerComponent.getSize());
      component.update2ndStep();
      activeComponents.add(component);
      pos2+=playerComponent.getSize();
    }
    if (!allFit) {
      Component.Instance component=morePlayersComponent.toInstance(serverContext.derived().put(Context.KEY_OTHER_PLAYERS_COUNT,players.size() - j));
      component.activate();
      component.update1stStep();
      component.setPosition(leftMostColumn,row + ((pos + pos2) / context.get(Context.KEY_COLUMNS)),leftMostColumn + ((pos + pos2) % context.get(Context.KEY_COLUMNS)),morePlayersComponent.getSize());
      component.update2ndStep();
      activeComponents.add(component);
      pos2+=morePlayersComponent.getSize();
    }
    if (serverFooter != null) {
      pos+=serverSize;
      Component.Instance footer=serverFooter.toInstance(serverContext);
      footer.activate();
      footer.update1stStep();
      footer.setPosition(leftMostColumn,row + (pos / context.get(Context.KEY_COLUMNS)),leftMostColumn + (pos % context.get(Context.KEY_COLUMNS)),serverFooter.getSize());
      footer.update2ndStep();
      activeComponents.add(footer);
      pos+=serverFooter.getSize();
    }
 else {
      pos+=pos2;
    }
  }
}