Program: 112064
Project: 112064
Buggy source:
/** 
 * @param root the root of the schema
 * @param validating
 * @param columnsStore
 * @param unboundFilter Filter records, pass in NULL_FILTER to leave unfiltered.
 */
public RecordReaderImplementation(MessageColumnIO root,RecordMaterializer<T> recordMaterializer,boolean validating,ColumnReadStoreImpl columnStore,UnboundRecordFilter unboundFilter){
  this.recordMaterializer=recordMaterializer;
  this.recordConsumer=recordMaterializer.getRootConverter();
  PrimitiveColumnIO[] leaves=root.getLeaves().toArray(new PrimitiveColumnIO[root.getLeaves().size()]);
  ColumnReader[] columns=new ColumnReader[leaves.length];
  int[][] nextReader=new int[leaves.length][];
  int[][] nextLevel=new int[leaves.length][];
  GroupConverter[][] groupConverterPaths=new GroupConverter[leaves.length][];
  PrimitiveConverter[] primitiveConverters=new PrimitiveConverter[leaves.length];
  int[] firsts=new int[256];
  for (int i=0; i < leaves.length; i++) {
    PrimitiveColumnIO primitiveColumnIO=leaves[i];
    final int[] indexFieldPath=primitiveColumnIO.getIndexFieldPath();
    groupConverterPaths[i]=new GroupConverter[indexFieldPath.length - 1];
    GroupConverter current=this.recordConsumer;
    for (int j=0; j < indexFieldPath.length - 1; j++) {
      current=current.getConverter(indexFieldPath[j]).asGroupConverter();
      groupConverterPaths[i][j]=current;
    }
    primitiveConverters[i]=current.getConverter(indexFieldPath[indexFieldPath.length - 1]).asPrimitiveConverter();
    columns[i]=columnStore.getColumnReader(primitiveColumnIO.getColumnDescriptor());
    int repetitionLevel=primitiveColumnIO.getRepetitionLevel();
    nextReader[i]=new int[repetitionLevel + 1];
    nextLevel[i]=new int[repetitionLevel + 1];
    for (int r=0; r <= repetitionLevel; ++r) {
      if (primitiveColumnIO.isFirst(r)) {
        firsts[r]=i;
      }
      int next;
      if (r == 0) {
        next=i + 1;
      }
 else       if (primitiveColumnIO.isLast(r)) {
        next=firsts[r];
      }
 else {
        next=i + 1;
      }
      if (next == leaves.length) {
        nextLevel[i][r]=0;
      }
 else       if (primitiveColumnIO.isLast(r)) {
        ColumnIO parent=primitiveColumnIO.getParent(r);
        nextLevel[i][r]=parent.getFieldPath().length - 1;
      }
 else {
        nextLevel[i][r]=getCommonParentLevel(primitiveColumnIO.getFieldPath(),leaves[next].getFieldPath());
      }
      if (nextLevel[i][r] > leaves[i].getFieldPath().length - 1) {
        throw new ParquetEncodingException(Arrays.toString(leaves[i].getFieldPath()) + "String_Node_Str" + r+ "String_Node_Str"+ nextLevel[i][r]);
      }
      nextReader[i][r]=next;
    }
  }
  states=new State[leaves.length];
  for (int i=0; i < leaves.length; i++) {
    states[i]=new State(i,leaves[i],columns[i],nextLevel[i],groupConverterPaths[i],primitiveConverters[i]);
    int[] definitionLevelToDepth=new int[states[i].primitiveColumnIO.getDefinitionLevel() + 1];
    final ColumnIO[] path=states[i].primitiveColumnIO.getPath();
    int depth=0;
    for (int d=0; d < definitionLevelToDepth.length; ++d) {
      while (depth < (states[i].fieldPath.length - 1) && d >= path[depth + 1].getDefinitionLevel()) {
        ++depth;
      }
      definitionLevelToDepth[d]=depth - 1;
    }
    states[i].definitionLevelToDepth=definitionLevelToDepth;
  }
  for (int i=0; i < leaves.length; i++) {
    State state=states[i];
    int[] nextStateIds=nextReader[i];
    state.nextState=new State[nextStateIds.length];
    for (int j=0; j < nextStateIds.length; j++) {
      state.nextState[j]=nextStateIds[j] == states.length ? null : states[nextStateIds[j]];
    }
  }
  for (int i=0; i < states.length; i++) {
    State state=states[i];
    final Map<Case,Case> definedCases=new HashMap<Case,Case>();
    final Map<Case,Case> undefinedCases=new HashMap<Case,Case>();
    Case[][][] caseLookup=new Case[state.fieldPath.length][][];
    for (int currentLevel=0; currentLevel < state.fieldPath.length; ++currentLevel) {
      caseLookup[currentLevel]=new Case[state.maxDefinitionLevel + 1][];
      for (int d=0; d <= state.maxDefinitionLevel; ++d) {
        caseLookup[currentLevel][d]=new Case[state.maxRepetitionLevel + 1];
        for (int nextR=0; nextR <= state.maxRepetitionLevel; ++nextR) {
          int caseStartLevel=currentLevel;
          int caseDepth=Math.max(state.getDepth(d),caseStartLevel - 1);
          int caseNextLevel=Math.min(state.nextLevel[nextR],caseDepth + 1);
          Case currentCase=new Case(caseStartLevel,caseDepth,caseNextLevel,getNextReader(state.id,nextR),d == state.maxDefinitionLevel);
          Map<Case,Case> cases=currentCase.isDefined() ? definedCases : undefinedCases;
          if (!cases.containsKey(currentCase)) {
            currentCase.setID(cases.size());
            cases.put(currentCase,currentCase);
          }
 else {
            currentCase=cases.get(currentCase);
          }
          caseLookup[currentLevel][d][nextR]=currentCase;
        }
      }
    }
    state.caseLookup=caseLookup;
    state.definedCases=new ArrayList<Case>(definedCases.values());
    state.undefinedCases=new ArrayList<Case>(undefinedCases.values());
    Comparator<Case> caseComparator=new Comparator<Case>(){
      @Override public int compare(      Case o1,      Case o2){
        return o1.id - o2.id;
      }
    }
;
    Collections.sort(state.definedCases,caseComparator);
    Collections.sort(state.undefinedCases,caseComparator);
  }
  recordFilter=unboundFilter.bind((unboundFilter == RecordFilter.NULL_FILTER) ? null : ImmutableList.copyOf(columns));
}

Fixed version (ground truth):
/** 
 * @param root the root of the schema
 * @param validating
 * @param columnStore
 * @param unboundFilter Filter records, pass in NULL_FILTER to leave unfiltered.
 */
public RecordReaderImplementation(MessageColumnIO root,RecordMaterializer<T> recordMaterializer,boolean validating,ColumnReadStoreImpl columnStore,UnboundRecordFilter unboundFilter){
  this.recordMaterializer=recordMaterializer;
  this.recordConsumer=recordMaterializer.getRootConverter();
  PrimitiveColumnIO[] leaves=root.getLeaves().toArray(new PrimitiveColumnIO[root.getLeaves().size()]);
  ColumnReader[] columns=new ColumnReader[leaves.length];
  int[][] nextReader=new int[leaves.length][];
  int[][] nextLevel=new int[leaves.length][];
  GroupConverter[][] groupConverterPaths=new GroupConverter[leaves.length][];
  PrimitiveConverter[] primitiveConverters=new PrimitiveConverter[leaves.length];
  int[] firsts=new int[256];
  for (int i=0; i < leaves.length; i++) {
    PrimitiveColumnIO primitiveColumnIO=leaves[i];
    final int[] indexFieldPath=primitiveColumnIO.getIndexFieldPath();
    groupConverterPaths[i]=new GroupConverter[indexFieldPath.length - 1];
    GroupConverter current=this.recordConsumer;
    for (int j=0; j < indexFieldPath.length - 1; j++) {
      current=current.getConverter(indexFieldPath[j]).asGroupConverter();
      groupConverterPaths[i][j]=current;
    }
    primitiveConverters[i]=current.getConverter(indexFieldPath[indexFieldPath.length - 1]).asPrimitiveConverter();
    columns[i]=columnStore.getColumnReader(primitiveColumnIO.getColumnDescriptor());
    int repetitionLevel=primitiveColumnIO.getRepetitionLevel();
    nextReader[i]=new int[repetitionLevel + 1];
    nextLevel[i]=new int[repetitionLevel + 1];
    for (int r=0; r <= repetitionLevel; ++r) {
      if (primitiveColumnIO.isFirst(r)) {
        firsts[r]=i;
      }
      int next;
      if (r == 0) {
        next=i + 1;
      }
 else       if (primitiveColumnIO.isLast(r)) {
        next=firsts[r];
      }
 else {
        next=i + 1;
      }
      if (next == leaves.length) {
        nextLevel[i][r]=0;
      }
 else       if (primitiveColumnIO.isLast(r)) {
        ColumnIO parent=primitiveColumnIO.getParent(r);
        nextLevel[i][r]=parent.getFieldPath().length - 1;
      }
 else {
        nextLevel[i][r]=getCommonParentLevel(primitiveColumnIO.getFieldPath(),leaves[next].getFieldPath());
      }
      if (nextLevel[i][r] > leaves[i].getFieldPath().length - 1) {
        throw new ParquetEncodingException(Arrays.toString(leaves[i].getFieldPath()) + "String_Node_Str" + r+ "String_Node_Str"+ nextLevel[i][r]);
      }
      nextReader[i][r]=next;
    }
  }
  states=new State[leaves.length];
  for (int i=0; i < leaves.length; i++) {
    states[i]=new State(i,leaves[i],columns[i],nextLevel[i],groupConverterPaths[i],primitiveConverters[i]);
    int[] definitionLevelToDepth=new int[states[i].primitiveColumnIO.getDefinitionLevel() + 1];
    final ColumnIO[] path=states[i].primitiveColumnIO.getPath();
    int depth=0;
    for (int d=0; d < definitionLevelToDepth.length; ++d) {
      while (depth < (states[i].fieldPath.length - 1) && d >= path[depth + 1].getDefinitionLevel()) {
        ++depth;
      }
      definitionLevelToDepth[d]=depth - 1;
    }
    states[i].definitionLevelToDepth=definitionLevelToDepth;
  }
  for (int i=0; i < leaves.length; i++) {
    State state=states[i];
    int[] nextStateIds=nextReader[i];
    state.nextState=new State[nextStateIds.length];
    for (int j=0; j < nextStateIds.length; j++) {
      state.nextState[j]=nextStateIds[j] == states.length ? null : states[nextStateIds[j]];
    }
  }
  for (int i=0; i < states.length; i++) {
    State state=states[i];
    final Map<Case,Case> definedCases=new HashMap<Case,Case>();
    final Map<Case,Case> undefinedCases=new HashMap<Case,Case>();
    Case[][][] caseLookup=new Case[state.fieldPath.length][][];
    for (int currentLevel=0; currentLevel < state.fieldPath.length; ++currentLevel) {
      caseLookup[currentLevel]=new Case[state.maxDefinitionLevel + 1][];
      for (int d=0; d <= state.maxDefinitionLevel; ++d) {
        caseLookup[currentLevel][d]=new Case[state.maxRepetitionLevel + 1];
        for (int nextR=0; nextR <= state.maxRepetitionLevel; ++nextR) {
          int caseStartLevel=currentLevel;
          int caseDepth=Math.max(state.getDepth(d),caseStartLevel - 1);
          int caseNextLevel=Math.min(state.nextLevel[nextR],caseDepth + 1);
          Case currentCase=new Case(caseStartLevel,caseDepth,caseNextLevel,getNextReader(state.id,nextR),d == state.maxDefinitionLevel);
          Map<Case,Case> cases=currentCase.isDefined() ? definedCases : undefinedCases;
          if (!cases.containsKey(currentCase)) {
            currentCase.setID(cases.size());
            cases.put(currentCase,currentCase);
          }
 else {
            currentCase=cases.get(currentCase);
          }
          caseLookup[currentLevel][d][nextR]=currentCase;
        }
      }
    }
    state.caseLookup=caseLookup;
    state.definedCases=new ArrayList<Case>(definedCases.values());
    state.undefinedCases=new ArrayList<Case>(undefinedCases.values());
    Comparator<Case> caseComparator=new Comparator<Case>(){
      @Override public int compare(      Case o1,      Case o2){
        return o1.id - o2.id;
      }
    }
;
    Collections.sort(state.definedCases,caseComparator);
    Collections.sort(state.undefinedCases,caseComparator);
  }
  recordFilter=unboundFilter.bind((unboundFilter == RecordFilter.NULL_FILTER) ? null : ImmutableList.copyOf(columns));
}