Skip to content

Commit b8d3517

Browse files
shimatclaude
andcommitted
xfeatures2d: move DAISY ROI validation to the managed side
Keep the native bridge thin: xfeatures2d_DAISY_compute_roi goes back to a direct 1:1 mirror of cv::xfeatures2d::DAISY::compute(image, roi, descriptors), with a separate, single-purpose xfeatures2d_DAISY_getImageSize accessor added for size lookups. DAISY.Compute(InputArray, Rect, OutputArray) now validates roi against that size and throws ArgumentException itself, instead of the validation logic and CV_Error living in the C++ layer. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent 69e93ef commit b8d3517

4 files changed

Lines changed: 26 additions & 17 deletions

File tree

src/OpenCvSharp/Internal/PInvoke/NativeMethods/NativeMethods_xfeatures2d_DAISY.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ internal static partial ExceptionStatus xfeatures2d_DAISY_create(
6161
[LibraryImport(DllExtern), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
6262
public static partial ExceptionStatus xfeatures2d_DAISY_getUseOrientation(OpenCvSafeHandle obj, out int returnValue);
6363

64+
[LibraryImport(DllExtern), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
65+
internal static partial ExceptionStatus xfeatures2d_DAISY_getImageSize(in InputArrayProxy image, out Size returnValue);
66+
6467
[LibraryImport(DllExtern), UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
6568
internal static partial ExceptionStatus xfeatures2d_DAISY_compute_roi(
6669
OpenCvSafeHandle obj, in InputArrayProxy image, Rect roi, in OutputArrayProxy descriptors);

src/OpenCvSharp/Modules/xfeatures2d/DAISY.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,8 @@ public bool UseOrientation
199199
/// coordinates even though the buffer is only sized <c>roi.Width * roi.Height</c> rows,
200200
/// so it overflows unless <paramref name="roi"/> covers the entire image
201201
/// (<c>roi.X == 0 &amp;&amp; roi.Y == 0 &amp;&amp; roi.Width == image.Cols &amp;&amp; roi.Height == image.Rows</c>).
202-
/// The native bridge guards against this and throws <see cref="OpenCVException"/> instead of
203-
/// letting a partial ROI corrupt memory.
202+
/// This is validated up front and throws <see cref="ArgumentException"/> instead of letting a
203+
/// partial ROI corrupt memory.
204204
/// </remarks>
205205
/// <param name="image">Image to extract descriptors from.</param>
206206
/// <param name="roi">Region of interest within the image. Must cover the entire image (see remarks).</param>
@@ -209,6 +209,14 @@ public void Compute(InputArray image, Rect roi, OutputArray descriptors)
209209
{
210210
ThrowIfDisposed();
211211

212+
NativeMethods.HandleException(NativeMethods.xfeatures2d_DAISY_getImageSize(image.Proxy, out var imageSize));
213+
if (roi.X != 0 || roi.Y != 0 || roi.Width != imageSize.Width || roi.Height != imageSize.Height)
214+
{
215+
throw new ArgumentException(
216+
"Due to an upstream OpenCV bug, roi must cover the entire image " +
217+
"(X=0, Y=0, Width=image.Cols, Height=image.Rows).", nameof(roi));
218+
}
219+
212220
NativeMethods.HandleException(
213221
NativeMethods.xfeatures2d_DAISY_compute_roi(Handle, image.Proxy, roi, descriptors.Proxy));
214222
GC.KeepAlive(image.Source);

src/OpenCvSharpExtern/xfeatures2d_DAISY.h

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -110,24 +110,22 @@ CVAPI(ExceptionStatus) xfeatures2d_DAISY_getUseOrientation(cv::xfeatures2d::DAIS
110110
return cvTry([&] { *returnValue = obj->getUseOrientation() ? 1 : 0; });
111111
}
112112

113+
// Thin size accessor so the managed side (DAISY.Compute(InputArray, Rect, OutputArray)) can
114+
// validate roi against the image bounds itself before calling compute_roi below; see that
115+
// managed method for why the validation is needed (an upstream OpenCV buffer-overflow bug).
116+
CVAPI(ExceptionStatus) xfeatures2d_DAISY_getImageSize(const interop::InputArrayProxy *image, interop::Size *returnValue)
117+
{
118+
return cvTry([&] {
119+
const cv::Size sz = static_cast<const cv::_InputArray&>(InProxy(*image)).size();
120+
*returnValue = interop::Size{ sz.width, sz.height };
121+
});
122+
}
123+
113124
CVAPI(ExceptionStatus) xfeatures2d_DAISY_compute_roi(
114125
cv::xfeatures2d::DAISY *obj, const interop::InputArrayProxy *image, interop::Rect roi, const interop::OutputArrayProxy *descriptors)
115126
{
116127
return cvTry([&] {
117-
const InProxy imageProxy(*image);
118-
const cv::Rect roiRect = cpp(roi);
119-
// DAISY_Impl::compute_descriptors (opencv_contrib xfeatures2d/src/daisy.cpp) indexes its
120-
// output buffer using absolute image coordinates while sizing the buffer to only
121-
// roi.width*roi.height rows, so it overflows unless roi covers the entire image. Guard
122-
// here instead of silently corrupting memory.
123-
const cv::Size imageSize = static_cast<const cv::_InputArray&>(imageProxy).size();
124-
if (roiRect.x != 0 || roiRect.y != 0 || roiRect.width != imageSize.width || roiRect.height != imageSize.height)
125-
{
126-
CV_Error(cv::Error::StsBadArg,
127-
"DAISY.Compute(image, roi, descriptors): due to an upstream OpenCV bug, roi must cover "
128-
"the entire image (x=0, y=0, width=image.Cols, height=image.Rows)");
129-
}
130-
obj->compute(static_cast<const cv::_InputArray&>(imageProxy), roiRect, OutProxy(*descriptors));
128+
obj->compute(InProxy(*image), cpp(roi), OutProxy(*descriptors));
131129
});
132130
}
133131

test/OpenCvSharp.Tests/xfeatures2d/DAISYTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public void ComputeRoiWithPartialRoiThrows()
6464
using var descriptors = new Mat();
6565
using var daisy = DAISY.Create();
6666

67-
Assert.Throws<OpenCVException>(() => daisy.Compute(gray, new Rect(0, 10, gray.Cols, 50), descriptors));
67+
Assert.Throws<ArgumentException>(() => daisy.Compute(gray, new Rect(0, 10, gray.Cols, 50), descriptors));
6868
}
6969

7070
[Fact]

0 commit comments

Comments
 (0)