mirror of
https://github.com/opencv/opencv.git
synced 2026-07-29 15:23:05 +04:00
objdetect: fix out-of-bounds write in HOG gaussian weights (blockSize.height vs width)
In HOGCache::init the block gaussian weights are computed into two buffers: AutoBuffer<float> di(blockSize.height), dj(blockSize.width); The vectorized (CV_SIMD128) loop that fills dj was bounded by `blockSize.height` instead of `blockSize.width`. When the block is taller than it is wide, `v_store(_dj + j, ...)` writes past the end of the width-sized dj buffer, causing a heap buffer overflow / access violation (e.g. HOGDescriptor with a 198x281 window, or the 2399x2400 case from the report). Bound the dj loop by `blockSize.width` to match the buffer size and the scalar tail loop. This keeps the SIMD path (unlike the workaround in the report, which disabled it). Added a regression test that computes a HOGDescriptor with a tall block; without the fix it triggers a heap-buffer-overflow (confirmed with AddressSanitizer at hog.cpp:731 inside HOGCache::init). Fixes #23580
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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<float> descriptors;
|
||||
ASSERT_NO_THROW(hog.compute(src, descriptors));
|
||||
EXPECT_FALSE(descriptors.empty());
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
|
||||
Reference in New Issue
Block a user