Program: 3519
Project: 3519
Buggy source:
@Override public void onLayoutChildren(RecyclerView.Recycler recycler,RecyclerView.State state){
  if (getItemCount() == 0) {
    detachAndScrapAttachedViews(recycler);
    return;
  }
  if (getChildCount() == 0 && state.isPreLayout()) {
    return;
  }
  if (!state.isPreLayout()) {
    mFirstChangedPosition=mChangedPositionCount=0;
  }
  if (getChildCount() == 0) {
    View scrap=recycler.getViewForPosition(0);
    addView(scrap);
    measureChildWithMargins(scrap,0,0);
    mDecoratedChildWidth=getDecoratedMeasuredWidth(scrap);
    mDecoratedChildHeight=getDecoratedMeasuredHeight(scrap);
    detachAndScrapView(scrap,recycler);
  }
  updateWindowSizing();
  SparseIntArray removedCache=null;
  if (state.isPreLayout()) {
    removedCache=new SparseIntArray(getChildCount());
    for (int i=0; i < getChildCount(); i++) {
      final View view=getChildAt(i);
      LayoutParams lp=(LayoutParams)view.getLayoutParams();
      if (lp.isItemRemoved()) {
        removedCache.put(lp.getViewAdapterPosition(),REMOVE_VISIBLE);
      }
    }
    if (removedCache.size() == 0 && mChangedPositionCount > 0) {
      for (int i=mFirstChangedPosition; i < (mFirstChangedPosition + mChangedPositionCount); i++) {
        removedCache.put(i,REMOVE_INVISIBLE);
      }
    }
  }
  int childLeft;
  int childTop;
  if (getChildCount() == 0) {
    mFirstVisiblePosition=0;
    childLeft=childTop=0;
  }
 else   if (!state.isPreLayout() && getVisibleChildCount() >= state.getItemCount()) {
    mFirstVisiblePosition=0;
    childLeft=childTop=0;
  }
 else {
    final View topChild=getChildAt(0);
    if (mForceClearOffsets) {
      childLeft=childTop=0;
      mForceClearOffsets=false;
    }
 else {
      childLeft=getDecoratedLeft(topChild);
      childTop=getDecoratedTop(topChild);
    }
    if (!state.isPreLayout() && getVerticalSpace() > (getTotalRowCount() * mDecoratedChildHeight)) {
      mFirstVisiblePosition=mFirstVisiblePosition % getTotalColumnCount();
      childTop=0;
      if ((mFirstVisiblePosition + mVisibleColumnCount) > state.getItemCount()) {
        mFirstVisiblePosition=Math.max(state.getItemCount() - mVisibleColumnCount,0);
        childLeft=0;
      }
    }
    int maxFirstRow=getTotalRowCount() - (mVisibleRowCount - 1);
    int maxFirstCol=getTotalColumnCount() - (mVisibleColumnCount - 1);
    boolean isOutOfRowBounds=getFirstVisibleRow() > maxFirstRow;
    boolean isOutOfColBounds=getFirstVisibleColumn() > maxFirstCol;
    if (isOutOfRowBounds || isOutOfColBounds) {
      int firstRow;
      if (isOutOfRowBounds) {
        firstRow=maxFirstRow;
      }
 else {
        firstRow=getFirstVisibleRow();
      }
      int firstCol;
      if (isOutOfColBounds) {
        firstCol=maxFirstCol;
      }
 else {
        firstCol=getFirstVisibleColumn();
      }
      mFirstVisiblePosition=firstRow * getTotalColumnCount() + firstCol;
      childLeft=getHorizontalSpace() - (mDecoratedChildWidth * mVisibleColumnCount);
      childTop=getVerticalSpace() - (mDecoratedChildHeight * mVisibleRowCount);
      if (getFirstVisibleRow() == 0) {
        childTop=Math.min(childTop,0);
      }
      if (getFirstVisibleColumn() == 0) {
        childLeft=Math.min(childLeft,0);
      }
    }
  }
  detachAndScrapAttachedViews(recycler);
  fillGrid(DIRECTION_NONE,childLeft,childTop,recycler,state,removedCache);
  if (!state.isPreLayout() && !recycler.getScrapList().isEmpty()) {
    final List<RecyclerView.ViewHolder> scrapList=recycler.getScrapList();
    final HashSet<View> disappearingViews=new HashSet<View>(scrapList.size());
    for (    RecyclerView.ViewHolder holder : scrapList) {
      final View child=holder.itemView;
      final LayoutParams lp=(LayoutParams)child.getLayoutParams();
      if (!lp.isItemRemoved()) {
        disappearingViews.add(child);
      }
    }
    for (    View child : disappearingViews) {
      layoutDisappearingView(child);
    }
  }
}

Fixed version (ground truth):
@Override public void onLayoutChildren(RecyclerView.Recycler recycler,RecyclerView.State state){
  if (getItemCount() == 0) {
    detachAndScrapAttachedViews(recycler);
    return;
  }
  if (getChildCount() == 0 && state.isPreLayout()) {
    return;
  }
  if (!state.isPreLayout()) {
    mFirstChangedPosition=mChangedPositionCount=0;
  }
  if (getChildCount() == 0) {
    View scrap=recycler.getViewForPosition(0);
    addView(scrap);
    measureChildWithMargins(scrap,0,0);
    mDecoratedChildWidth=getDecoratedMeasuredWidth(scrap);
    mDecoratedChildHeight=getDecoratedMeasuredHeight(scrap);
    detachAndScrapView(scrap,recycler);
  }
  updateWindowSizing();
  SparseIntArray removedCache=null;
  if (state.isPreLayout()) {
    removedCache=new SparseIntArray(getChildCount());
    for (int i=0; i < getChildCount(); i++) {
      final View view=getChildAt(i);
      LayoutParams lp=(LayoutParams)view.getLayoutParams();
      if (lp.isItemRemoved()) {
        removedCache.put(lp.getViewLayoutPosition(),REMOVE_VISIBLE);
      }
    }
    if (removedCache.size() == 0 && mChangedPositionCount > 0) {
      for (int i=mFirstChangedPosition; i < (mFirstChangedPosition + mChangedPositionCount); i++) {
        removedCache.put(i,REMOVE_INVISIBLE);
      }
    }
  }
  int childLeft;
  int childTop;
  if (getChildCount() == 0) {
    mFirstVisiblePosition=0;
    childLeft=childTop=0;
  }
 else   if (!state.isPreLayout() && getVisibleChildCount() >= state.getItemCount()) {
    mFirstVisiblePosition=0;
    childLeft=childTop=0;
  }
 else {
    final View topChild=getChildAt(0);
    if (mForceClearOffsets) {
      childLeft=childTop=0;
      mForceClearOffsets=false;
    }
 else {
      childLeft=getDecoratedLeft(topChild);
      childTop=getDecoratedTop(topChild);
    }
    if (!state.isPreLayout() && getVerticalSpace() > (getTotalRowCount() * mDecoratedChildHeight)) {
      mFirstVisiblePosition=mFirstVisiblePosition % getTotalColumnCount();
      childTop=0;
      if ((mFirstVisiblePosition + mVisibleColumnCount) > state.getItemCount()) {
        mFirstVisiblePosition=Math.max(state.getItemCount() - mVisibleColumnCount,0);
        childLeft=0;
      }
    }
    int maxFirstRow=getTotalRowCount() - (mVisibleRowCount - 1);
    int maxFirstCol=getTotalColumnCount() - (mVisibleColumnCount - 1);
    boolean isOutOfRowBounds=getFirstVisibleRow() > maxFirstRow;
    boolean isOutOfColBounds=getFirstVisibleColumn() > maxFirstCol;
    if (isOutOfRowBounds || isOutOfColBounds) {
      int firstRow;
      if (isOutOfRowBounds) {
        firstRow=maxFirstRow;
      }
 else {
        firstRow=getFirstVisibleRow();
      }
      int firstCol;
      if (isOutOfColBounds) {
        firstCol=maxFirstCol;
      }
 else {
        firstCol=getFirstVisibleColumn();
      }
      mFirstVisiblePosition=firstRow * getTotalColumnCount() + firstCol;
      childLeft=getHorizontalSpace() - (mDecoratedChildWidth * mVisibleColumnCount);
      childTop=getVerticalSpace() - (mDecoratedChildHeight * mVisibleRowCount);
      if (getFirstVisibleRow() == 0) {
        childTop=Math.min(childTop,0);
      }
      if (getFirstVisibleColumn() == 0) {
        childLeft=Math.min(childLeft,0);
      }
    }
  }
  detachAndScrapAttachedViews(recycler);
  fillGrid(DIRECTION_NONE,childLeft,childTop,recycler,state,removedCache);
  if (!state.isPreLayout() && !recycler.getScrapList().isEmpty()) {
    final List<RecyclerView.ViewHolder> scrapList=recycler.getScrapList();
    final HashSet<View> disappearingViews=new HashSet<View>(scrapList.size());
    for (    RecyclerView.ViewHolder holder : scrapList) {
      final View child=holder.itemView;
      final LayoutParams lp=(LayoutParams)child.getLayoutParams();
      if (!lp.isItemRemoved()) {
        disappearingViews.add(child);
      }
    }
    for (    View child : disappearingViews) {
      layoutDisappearingView(child);
    }
  }
}