diff --git a/modules/objdetect/src/hog.cpp b/modules/objdetect/src/hog.cpp index 1c7c8f73cb..7194b068ff 100644 --- a/modules/objdetect/src/hog.cpp +++ b/modules/objdetect/src/hog.cpp @@ -723,7 +723,7 @@ void HOGCache::init(const HOGDescriptor* _descriptor, #if CV_SIMD128 idx = v_float32x4(0.0f, 1.0f, 2.0f, 3.0f); - for (; j <= blockSize.height - 4; j += 4) + for (; j <= blockSize.width - 4; j += 4) { v_float32x4 t = v_sub(idx, _bw); t = v_mul(t, t); diff --git a/modules/objdetect/test/test_cascadeandhog.cpp b/modules/objdetect/test/test_cascadeandhog.cpp index 08c78f8ae5..ddec0e7b25 100644 --- a/modules/objdetect/test/test_cascadeandhog.cpp +++ b/modules/objdetect/test/test_cascadeandhog.cpp @@ -1364,4 +1364,22 @@ TEST(Objdetect_CascadeDetector, small_img) } } +// See https://github.com/opencv/opencv/issues/23580 +// HOGDescriptor::compute() overflowed the gaussian weights buffer when the block +// was taller than it was wide: the SIMD store loop for the width buffer (_dj) was +// bounded by blockSize.height instead of blockSize.width. The block is chosen wide +// enough that the buffer is heap allocated, so the overflow is a real out-of-bounds +// write. "Done" is simply that compute() runs without crashing. +TEST(Objdetect_HOGDescriptor, issue_23580_tall_block_no_overflow) +{ + Size winSize(272, 2048); // height > width, width > AutoBuffer stack size + HOGDescriptor hog(winSize, /*blockSize*/ winSize, /*blockStride*/ Size(8, 8), + /*cellSize*/ Size(8, 8), /*nbins*/ 9); + + Mat src(winSize, CV_8UC1, Scalar::all(0)); + std::vector descriptors; + ASSERT_NO_THROW(hog.compute(src, descriptors)); + EXPECT_FALSE(descriptors.empty()); +} + }} // namespace