Program: 97788
Project: 97788
Buggy source:
protected void erosion(SnipeData v,int erodeFaces,int erodeRec,int fillFaces,int fillRec){
  int brushSize=(int)v.getBrushSize() + 1;
  double brushSizeSquared=v.getBrushSize() * v.getBrushSize();
  int tx=this.targetBlock.getBlockX();
  int ty=this.targetBlock.getBlockY();
  int tz=this.targetBlock.getBlockZ();
  BlockBuffer buffer1=new BlockBuffer(new Vector3i(-brushSize - 1,-brushSize - 1,-brushSize - 1),new Vector3i(brushSize + 1,brushSize + 1,brushSize + 1));
  BlockBuffer buffer2=new BlockBuffer(new Vector3i(-brushSize - 1,-brushSize - 1,-brushSize - 1),new Vector3i(brushSize + 1,brushSize + 1,brushSize + 1));
  for (int x=-brushSize + 1; x <= brushSize + 1; x++) {
    int x0=x + tx;
    for (int y=-brushSize + 1; y <= brushSize + 1; y++) {
      int y0=y + ty;
      for (int z=-brushSize + 1; z <= brushSize + 1; z++) {
        int z0=z + tz;
        buffer1.set(x,y,z,this.world.getBlock(x0,y0,z0));
        buffer2.set(x,y,z,this.world.getBlock(x0,y0,z0));
      }
    }
  }
  int swap=0;
  for (int i=0; i < erodeRec; ++i) {
    erosionIteration(v,erodeFaces,swap % 2 == 0 ? buffer1 : buffer2,swap % 2 == 1 ? buffer1 : buffer2);
    swap++;
  }
  for (int i=0; i < fillRec; ++i) {
    fillIteration(v,fillFaces,swap % 2 == 0 ? buffer1 : buffer2,swap % 2 == 1 ? buffer1 : buffer2);
    swap++;
  }
  BlockBuffer finalBuffer=swap % 2 == 0 ? buffer1 : buffer2;
  this.undo=new Undo(finalBuffer.getBlockCount());
  for (int x=-brushSize; x <= brushSize; x++) {
    int x0=x + tx;
    for (int y=-brushSize; y <= brushSize; y++) {
      int y0=y + ty;
      for (int z=-brushSize; z <= brushSize; z++) {
        int z0=z + tz;
        if (x * x + y * y + z * z >= brushSizeSquared && finalBuffer.contains(x,y,z)) {
          setBlockState(x0,y0,z0,finalBuffer.get(x,y,z));
        }
      }
    }
  }
  v.owner().storeUndo(this.undo);
  this.undo=null;
}

Fixed version (ground truth):
protected void erosion(SnipeData v,int erodeFaces,int erodeRec,int fillFaces,int fillRec){
  int brushSize=(int)Math.ceil(v.getBrushSize());
  double brushSizeSquared=v.getBrushSize() * v.getBrushSize();
  int tx=this.targetBlock.getBlockX();
  int ty=this.targetBlock.getBlockY();
  int tz=this.targetBlock.getBlockZ();
  BlockBuffer buffer1=new BlockBuffer(new Vector3i(-brushSize - 1,-brushSize - 1,-brushSize - 1),new Vector3i(brushSize + 1,brushSize + 1,brushSize + 1));
  BlockBuffer buffer2=new BlockBuffer(new Vector3i(-brushSize - 1,-brushSize - 1,-brushSize - 1),new Vector3i(brushSize + 1,brushSize + 1,brushSize + 1));
  for (int x=-brushSize - 1; x <= brushSize + 1; x++) {
    int x0=x + tx;
    for (int y=-brushSize - 1; y <= brushSize + 1; y++) {
      int y0=y + ty;
      for (int z=-brushSize - 1; z <= brushSize + 1; z++) {
        int z0=z + tz;
        BlockState state=this.world.getBlock(x0,y0,z0);
        buffer1.set(x,y,z,state);
        buffer2.set(x,y,z,state);
      }
    }
  }
  int swap=0;
  for (int i=0; i < erodeRec; ++i) {
    erosionIteration(v,erodeFaces,swap % 2 == 0 ? buffer1 : buffer2,swap % 2 == 1 ? buffer1 : buffer2);
    swap++;
  }
  for (int i=0; i < fillRec; ++i) {
    fillIteration(v,fillFaces,swap % 2 == 0 ? buffer1 : buffer2,swap % 2 == 1 ? buffer1 : buffer2);
    swap++;
  }
  BlockBuffer finalBuffer=swap % 2 == 0 ? buffer1 : buffer2;
  this.undo=new Undo(finalBuffer.getBlockCount());
  for (int x=-brushSize; x <= brushSize; x++) {
    int x0=x + tx;
    for (int y=-brushSize; y <= brushSize; y++) {
      int y0=y + ty;
      for (int z=-brushSize; z <= brushSize; z++) {
        int z0=z + tz;
        if (x * x + y * y + z * z <= brushSizeSquared && finalBuffer.contains(x,y,z)) {
          setBlockState(x0,y0,z0,finalBuffer.get(x,y,z));
        }
      }
    }
  }
  v.owner().storeUndo(this.undo);
  this.undo=null;
}