mirror of
https://github.com/opencv/opencv.git
synced 2026-09-11 04:43:22 -05:00
Merge pull request #29069 from perrylin4:fix/11988-rect-unsigned-intersection
core: fix unsigned Rect intersection for disjoint rectangles (#11988) - #29069 Fixes #11988 ## Problem `Rect_<_Tp>::operator&` / `operator&=` returned a non-empty rectangle when two **unsigned** rectangles do not overlap. ### Example: ```cpp cv::Rect_<unsigned> r1(0, 0, 1, 1); cv::Rect_<unsigned> r2(2, 2, 1, 1); auto inter = r1 & r2; // was [1 x 1 from (2, 2)], expected empty ``` Root cause: the previous implementation subtracted edge coordinates before checking overlap. For `unsigned _Tp`, expressions like `width - (x_max - x_min)` can underflow when rectangles are disjoint. ### Solution Add a check for underflow ### Tests Added regression test `Core_Rect.test_unsigned_overflow in modules/core/test/test_misc.cpp`.
This commit is contained in:
@@ -2012,6 +2012,15 @@ Rect_<_Tp>& operator &= ( Rect_<_Tp>& a, const Rect_<_Tp>& b )
|
||||
a = Rect_<_Tp>();
|
||||
return a;
|
||||
}
|
||||
|
||||
// If the delta between x/y coordinates exceeds the corresponding width/height,
|
||||
// the rectangles cannot overlap and `width - delta` would underflow for unsigned types.
|
||||
if (Rx_min.width < (Rx_max.x - Rx_min.x) ||
|
||||
Ry_min.height < (Ry_max.y - Ry_min.y)) {
|
||||
a = Rect_<_Tp>();
|
||||
return a;
|
||||
}
|
||||
|
||||
// We now know that either Rx_min.x >= 0, or
|
||||
// Rx_min.x < 0 && Rx_min.x + Rx_min.width >= Rx_max.x and therefore
|
||||
// Rx_min.width >= (Rx_max.x - Rx_min.x) which means (Rx_max.x - Rx_min.x)
|
||||
|
||||
@@ -996,6 +996,17 @@ REGISTER_TYPED_TEST_CASE_P(Rect_Test, Overflows, OnTheEdge);
|
||||
typedef ::testing::Types<int, float, double> RectTypes;
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(Negative_Test, Rect_Test, RectTypes);
|
||||
|
||||
TEST(Core_Rect, test_unsigned_overflow_11988)
|
||||
{
|
||||
typedef Rect_<unsigned> R;
|
||||
R r1(0, 0, 1u, 1u);
|
||||
R r2(2u, 2u, 1u, 1u);
|
||||
auto inter = r1 & r2;
|
||||
EXPECT_EQ(R(), inter);
|
||||
EXPECT_EQ(0u, inter.area());
|
||||
EXPECT_TRUE(inter.empty());
|
||||
}
|
||||
|
||||
// Expected that SkipTestException thrown in the constructor should skip test but not fail
|
||||
struct TestFixtureSkip: public ::testing::Test {
|
||||
TestFixtureSkip(bool throwEx = true) {
|
||||
|
||||
Reference in New Issue
Block a user