Files
CodeCraftsman 889ad964a1 Merge pull request #29715 from Thebinary110:fix-dis-opticalflow-overflow
video: fix DISOpticalFlow heap-buffer-overflow with patch_size > border_size - #29715

Fixes #20185.

### What
`DISOpticalFlowImpl` pads `I1` of every pyramid level with a **fixed 16 pixel border** (`border_size`), while `PatchInverseSearch` clamps a patch's sample position to:
```cpp
float i_lower_limit = bsz - psz + 1.0f;   // bsz = border_size, psz = patch_size
float i_upper_limit = bsz + dis->h - 1.0f;
```
i.e. a patch may be placed up to `patch_size - 1` pixels outside of the image. `computeSSD()`/`computeSSDMeanNorm()` then read `patch_size` (+1 for bilinear interpolation) rows/columns starting at that clamped position, which stays inside the padded buffer only while `patch_size <= border_size`. `patch_size` is user-settable via `setPatchSize()` with no upper bound relative to the hardcoded `border_size` -- so `setPatchSize()` past 16, or a temporal-candidate flow large enough to push the clamped search against its limit, reads past the end of `I1s_ext` (confirmed via AddressSanitizer: heap-buffer-overflow in `computeSSDMeanNorm`).

### Fix
Size the border to whichever is larger, exactly once, at the top of `prepareBuffers()` (where every `I1s_ext[i]` already gets freshly created/padded on every `calc()` call, so this doesn't need any additional cache-invalidation logic):
```cpp
border_size = max(16, patch_size);
```
The needed inequality (`border_size >= patch_size`) is independent of image size, so this is sufficient at every pyramid level uniformly. `ocl_prepareBuffers()` does not need the equivalent change: `calc()`'s `CV_OCL_RUN` gate only takes the OpenCL path when `patch_size == 8` exactly, which is always within the hardcoded border, so that path can never reach this overflow.

### On the prior attempt
A prior attempt at this exact fix (#29600) was closed by @asmorkalov, who ran its own added regression test and got the same ASan heap-buffer-overflow again ("the patch is not efficient"). I want to be upfront about this rather than just re-submitting the same-looking diff: **I could not reproduce that failure.** I reproduced the original overflow on unfixed 5.x (same crash site / allocator stack as both the original issue report and #29600's own ASan trace), then applied the same one-line fix and ran #29600's own added test 20x plus a new 40-trial randomized stress test (`patch_size` 9-48 -- spanning above and below `border_size=16` -- varying image size, `patch_stride`, flow magnitude up to 120px, and a same-instance second `calc()` call to exercise buffer re-use across a patch-size change) under AddressSanitizer, with zero failures. I don't have a confirmed explanation for the discrepancy -- possibly a stale incremental build on the original attempt's end, since I hit and had to work around exactly that kind of false "no work to do" ninja build-cache issue myself while setting up this reproduction. Flagging this openly rather than asserting certainty either way -- happy to dig further if CI or review surfaces a case this doesn't cover.

### Testing
Verified locally with a dedicated ASan-instrumented Debug build (`-fsanitize=address`, separate from the Release build used to verify the rest of today's changes), specifically because an out-of-bounds read like this often just silently returns garbage in a Release build instead of crashing:
- Confirmed the crash reproduces on unfixed 5.x, and is gone with the fix, under both `regression_20185_patch_larger_than_border` (from #29600, included here) and a new `regression_20185_stress` test (40 randomized trials) -- both passing cleanly under ASan.
- Re-verified both tests pass in the standard Release configuration too.
- Full `opencv_test_video` suite (both ASan and Release): no failures attributable to this change; everything else failing needs `opencv_extra` test data (tracking/ECC/optical-flow reference videos/images) not configured in this scoped build.

### PR checklist
- [x] I agree to contribute to the project under Apache 2 License.
- [x] To the best of my knowledge, the proposed patch is not based on code under GPL or another incompatible license.
- [x] The PR is proposed to the proper branch (5.x).
- [x] Accuracy tests included (see above).
- [x] No public API/behavior change, so no documentation or sample updates needed.
2026-09-21 13:53:05 +03:00
..
2026-06-01 14:22:51 +03:00
2025-02-20 13:58:04 +03:00