mirror of
https://github.com/opencv/opencv.git
synced 2026-11-09 18:04:29 -06:00
Merge pull request #30344 from spicysharkco:fix/validate-disparity-oob-5.x
stereo: fix out-of-bounds access in validateDisparity (5.x port of #30316)
This commit is contained in:
@@ -2550,6 +2550,9 @@ void validateDisparity( InputOutputArray _disp, InputArray _cost, int minDispari
|
||||
|
||||
int x2 = x - ((d + DISP_SCALE/2) >> DISP_SHIFT);
|
||||
|
||||
if( (unsigned)x2 >= (unsigned)cols )
|
||||
continue;
|
||||
|
||||
if( disp2cost[x2] > c )
|
||||
{
|
||||
disp2cost[x2] = c;
|
||||
@@ -2570,6 +2573,9 @@ void validateDisparity( InputOutputArray _disp, InputArray _cost, int minDispari
|
||||
|
||||
int x2 = x - ((d + DISP_SCALE/2) >> DISP_SHIFT);
|
||||
|
||||
if( (unsigned)x2 >= (unsigned)cols )
|
||||
continue;
|
||||
|
||||
if( disp2cost[x2] > c )
|
||||
{
|
||||
disp2cost[x2] = c;
|
||||
|
||||
@@ -952,6 +952,63 @@ TEST(Calib3d_StereoSGBM, deterministic) {
|
||||
|
||||
}
|
||||
|
||||
/* < cost type, x2 is past the last column (otherwise it is before the first one) > */
|
||||
typedef tuple < int, bool > ValidateDisparity_Params_t;
|
||||
|
||||
typedef testing::TestWithParam< ValidateDisparity_Params_t > Calib3d_ValidateDisparity;
|
||||
|
||||
TEST_P(Calib3d_ValidateDisparity, out_of_range_disparity)
|
||||
{
|
||||
const int costType = get<0>(GetParam());
|
||||
const bool pastEnd = get<1>(GetParam());
|
||||
|
||||
// The row is wide enough for validateDisparity to allocate its work buffer (2*cols ints) on the heap
|
||||
// with no spare capacity: AutoBuffer grows its inline capacity by 1.5x at least, which would hide
|
||||
// a read just past the end of a smaller buffer.
|
||||
const int cols = 256, numberOfDisparities = 16, disp12MaxDiff = 0;
|
||||
const int minDisparity = pastEnd ? 0 : 2;
|
||||
const short invalid = (short)((minDisparity - 1)*16);
|
||||
|
||||
struct Px { int x; short d; int cost; short expected; };
|
||||
std::vector<Px> pixels;
|
||||
if( pastEnd )
|
||||
{
|
||||
// disparity -2 at x = 255 gives x2 = 257 >= cols
|
||||
pixels.push_back({100, 80, 0, 80});
|
||||
pixels.push_back({255, -32, 0, -32});
|
||||
}
|
||||
else
|
||||
{
|
||||
// x = 250 and x = 251 both map to slot 248, 250 has the lower cost, so 251 fails the cross-check.
|
||||
// x = 255 gives x2 = -8, which is outside the buffer and used to overwrite the cost of slot 248.
|
||||
pixels.push_back({250, 32, 0, 32});
|
||||
pixels.push_back({251, 48, 10, invalid});
|
||||
pixels.push_back({255, 4208, 0, 4208});
|
||||
}
|
||||
|
||||
Mat1s disp(1, cols, invalid), expected(1, cols, invalid);
|
||||
Mat1i cost32(1, cols, 0);
|
||||
for( size_t i = 0; i < pixels.size(); i++ )
|
||||
{
|
||||
disp(0, pixels[i].x) = pixels[i].d;
|
||||
cost32(0, pixels[i].x) = pixels[i].cost;
|
||||
expected(0, pixels[i].x) = pixels[i].expected;
|
||||
}
|
||||
Mat cost;
|
||||
cost32.convertTo(cost, costType);
|
||||
|
||||
validateDisparity(disp, cost, minDisparity, numberOfDisparities, disp12MaxDiff);
|
||||
|
||||
EXPECT_EQ(0, cvtest::norm(disp, expected, NORM_INF));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/*nothing*/, Calib3d_ValidateDisparity,
|
||||
testing::Combine(
|
||||
testing::Values(CV_16S, CV_32S),
|
||||
testing::Bool()
|
||||
)
|
||||
);
|
||||
|
||||
TEST(Calib3d_StereoSGBM_HH4, regression)
|
||||
{
|
||||
String path = cvtest::TS::ptr()->get_data_path() + "cv/stereomatching/datasets/teddy/";
|
||||
|
||||
Reference in New Issue
Block a user