Skip to content

Commit

Permalink
Fix illegal extent request in ImageThresholdConnectivity.
Browse files Browse the repository at this point in the history
When asked for an output extent that was smaller than the input extent,
this filter would pass an illegal extent to GetScalarPointerForExtent().
It is possible that older versions of VTK would allow this, but in VTK 6
it raises an error.  It has a high probability of causing a segfault.

Change-Id: Ic024f9aa97335f1ba29b47be89a4e5be8195b00f
  • Loading branch information
dgobbi committed Sep 18, 2014
1 parent 819e9a6 commit 2426564
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 11 deletions.
7 changes: 7 additions & 0 deletions Imaging/Morphological/Testing/Cxx/CMakeLists.txt
@@ -0,0 +1,7 @@
vtk_add_test_cxx(${vtk-module}CxxTests tests
TestImageThresholdConnectivity.cxx
)

vtk_test_cxx_executable(${vtk-module}CxxTests tests
RENDERING_FACTORY
)
133 changes: 133 additions & 0 deletions Imaging/Morphological/Testing/Cxx/TestImageThresholdConnectivity.cxx
@@ -0,0 +1,133 @@
/*=========================================================================
Program: Visualization Toolkit
Module: TestImageThresholdConnectivity.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
// Test the vtkImageThresholdConnectivity class
//
// The command line arguments are:
// -I => run in interactive mode

#include "vtkCamera.h"
#include "vtkImageData.h"
#include "vtkImageProperty.h"
#include "vtkImageReader2.h"
#include "vtkImageSlice.h"
#include "vtkImageSliceMapper.h"
#include "vtkImageThresholdConnectivity.h"
#include "vtkInteractorStyleImage.h"
#include "vtkPoints.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkRenderer.h"
#include "vtkSmartPointer.h"

#include "vtkTestUtilities.h"

int TestImageThresholdConnectivity(int argc, char *argv[])
{
vtkSmartPointer<vtkRenderWindowInteractor> iren =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
vtkSmartPointer<vtkInteractorStyleImage> style =
vtkSmartPointer<vtkInteractorStyleImage>::New();
style->SetInteractionModeToImageSlicing();
vtkSmartPointer<vtkRenderWindow> renWin =
vtkSmartPointer<vtkRenderWindow>::New();
iren->SetRenderWindow(renWin);
iren->SetInteractorStyle(style);

char* fname =
vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/headsq/quarter");

vtkSmartPointer<vtkImageReader2> reader =
vtkSmartPointer<vtkImageReader2>::New();
reader->SetDataByteOrderToLittleEndian();
reader->SetDataExtent(0, 63, 0, 63, 2, 4);
reader->SetDataSpacing(3.2, 3.2, 1.5);
reader->SetFilePrefix(fname);

delete [] fname;

vtkSmartPointer<vtkPoints> seeds =
vtkSmartPointer<vtkPoints>::New();
seeds->InsertNextPoint(1, 1, 5.25);
seeds->InsertNextPoint(100.8, 100.8, 5.25);

for (int i = 0; i < 12; i++)
{
int j = i % 4;
int k = i / 4;
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
vtkCamera *camera = renderer->GetActiveCamera();
renderer->SetBackground(0.0, 0.0, 0.0);
renderer->SetViewport(k/3.0, j/4.0, (k + 1)/3.0, (j + 1)/4.0);
renWin->AddRenderer(renderer);

vtkSmartPointer<vtkImageThresholdConnectivity> connectivity =
vtkSmartPointer<vtkImageThresholdConnectivity>::New();
connectivity->SetInputConnection(reader->GetOutputPort());
connectivity->SetSeedPoints(seeds);
connectivity->SetInValue(2000);
connectivity->SetOutValue(0);
connectivity->SetReplaceIn((j & 2) == 0);
connectivity->SetReplaceOut((j & 1) == 0);
if (k == 0)
{
connectivity->ThresholdByLower(800);
}
else if (k == 1)
{
connectivity->ThresholdByUpper(1200);
}
else
{
connectivity->ThresholdBetween(800, 1200);
}

// test a previous bug where OutputExtent != InputExtent cause a crash.
int extent[6] = { 0, 63, 0, 63, 3, 3 };
connectivity->UpdateInformation();
connectivity->SetUpdateExtent(extent);
connectivity->Update();

vtkSmartPointer<vtkImageSliceMapper> imageMapper =
vtkSmartPointer<vtkImageSliceMapper>::New();
imageMapper->SetInputConnection(connectivity->GetOutputPort());
imageMapper->BorderOn();
imageMapper->SliceFacesCameraOn();
imageMapper->SliceAtFocalPointOn();

double point[3] = { 100.8, 100.8, 5.25 };
camera->SetFocalPoint(point);
point[2] += 500.0;
camera->SetPosition(point);
camera->SetViewUp(0.0, 1.0, 0.0);
camera->ParallelProjectionOn();
camera->SetParallelScale(3.2*32);

vtkSmartPointer<vtkImageSlice> image =
vtkSmartPointer<vtkImageSlice>::New();
image->SetMapper(imageMapper);
image->GetProperty()->SetColorWindow(2000);
image->GetProperty()->SetColorLevel(1000);
renderer->AddViewProp(image);
}

renWin->SetSize(192, 256);

iren->Initialize();
renWin->Render();
iren->Start();

return EXIT_SUCCESS;
}
@@ -0,0 +1 @@
743051aab9188a75d9ecc13a506d27fa
5 changes: 5 additions & 0 deletions Imaging/Morphological/module.cmake
Expand Up @@ -5,6 +5,11 @@ vtk_module(vtkImagingMorphological
DEPENDS
vtkImagingCore
vtkImagingGeneral
TEST_DEPENDS
vtkInteractionStyle
vtkInteractionImage
vtkRendering${VTK_RENDERING_BACKEND}
vtkTestingRendering
KIT
vtkImaging
)
25 changes: 14 additions & 11 deletions Imaging/Morphological/vtkImageThresholdConnectivity.cxx
Expand Up @@ -442,10 +442,22 @@ void vtkImageThresholdConnectivityExecute(

unsigned char *maskPtr =
static_cast<unsigned char *>(maskData->GetScalarPointerForExtent(extent));
vtkIdType maskInc[3];
maskInc[0] = 1;
maskInc[1] = (extent[1] - extent[0] + 1);
maskInc[2] = maskInc[1]*(extent[3] - extent[2] + 1);

// Get pointers for the new extent (the one used for the seeds)
// Get input pointer for the extent used by the maskData
inPtr = static_cast<IT *>(inData->GetScalarPointerForExtent(extent));
outPtr = static_cast<OT *>(outData->GetScalarPointerForExtent(extent));
vtkIdType inInc[3];
inData->GetIncrements(inInc);

// Get output pointer for the whole output extent
outPtr = static_cast<OT *>(outData->GetScalarPointerForExtent(outExt));
vtkIdType outInc[3];
outData->GetIncrements(outInc);
// Adjust it so that it corresponds to the maskData extent
outPtr -= minOutIdX*outInc[0] + minOutIdY*outInc[1] + minOutIdZ*outInc[2];

// Adjust pointers to active component
inPtr += activeComponent;
Expand Down Expand Up @@ -478,15 +490,6 @@ void vtkImageThresholdConnectivityExecute(
}

// Perform the flood fill within the extent
vtkIdType inInc[3];
vtkIdType outInc[3];
vtkIdType maskInc[3];
inData->GetIncrements(inInc);
outData->GetIncrements(outInc);
maskInc[0] = 1;
maskInc[1] = (extent[1] - extent[0] + 1);
maskInc[2] = maskInc[1]*(extent[3] - extent[2] + 1);

double spacing[3];
double origin[3];
outData->GetSpacing(spacing);
Expand Down

0 comments on commit 2426564

Please sign in to comment.