Skip to content

Fix out-of-bounds access in EdgeAwareInterpolator when k exceeds match count - #4201

Open
Huxingyu wants to merge 1 commit into
opencv:4.xfrom
Huxingyu:fix-4195-sparse-match-interpolator
Open

Fix out-of-bounds access in EdgeAwareInterpolator when k exceeds match count#4201
Huxingyu wants to merge 1 commit into
opencv:4.xfrom
Huxingyu:fix-4195-sparse-match-interpolator

Conversation

@Huxingyu

Copy link
Copy Markdown

Pull Request Checklist

  • There are no new and unexpected changes
  • All existing and new tests pass
  • Code complies with OpenCV coding style
  • This PR is submitted to the correct branch (4.x)

Summary

Fixes #4195: calcOpticalFlowSparseToDense (or direct EdgeAwareInterpolator use) crashes when the configured k exceeds the actual number of sparse matches.

Root cause

EdgeAwareInterpolatorImpl::interpolate allocates NNlabels as match_num x k and pre-fills it with the -1 sentinel. The KNN pass only fills as many entries as it can actually expand, and the RANSAC pass reads exactly k entries per row. When k > match_num (e.g. the default k=128 with the 48x64 / grid_step=8 case from the issue, which samples only 48 grid points), the RANSAC pass reads the -1 sentinels and dereferences matches[-1] / transforms[-1], crashing.

Fix

  • Use num_neighbors = min(k, match_num) for the current call only; the user's k (and getK()) stays unchanged.
  • Operate all KNN/RANSAC passes on num_neighbors, so the -1 sentinels are never consumed.
  • Reject degenerate input with a clear cv::Exception: fewer than 3 unique matches, or k < 3 (the RANSAC affine fit needs 3 points).

Tests

  • DenseOpticalFlow_SparseToDenseFlow.Regression_4195 (optflow): default 48x64 input no longer crashes; 8x8 input throws cv::Exception.
  • InterpolatorTest.RejectsTooFewMatches (ximgproc): 0/1/2 matches throw StsBadArg.
  • InterpolatorTest.KExceedsMatchCount (ximgproc): k=128 with 5 matches produces valid flow and leaves getK()==128 unchanged.

Validation

Built opencv_test_optflow / opencv_test_ximgproc locally (ASan build) and ran the new regression tests plus the existing InterpolatorTest.MultiThreadReproducibility suite — all pass. The standalone repro from the issue no longer crashes under ASan. Data-dependent reference tests require opencv_extra and run in CI.

…h count

The default k=128 exceeds the number of matches sampled on small images
(e.g. 48x64 with grid_step 8), leaving -1 sentinel labels in NNlabels that
were later read as matches[-1]/transforms[-1], causing a crash.

Clamp the neighbors used per call to min(k, match_num) without mutating the
user's k, and reject fewer than 3 matches or neighbors with cv::Exception.
The RANSAC/KNN passes now operate on the clamped neighbor count, so no -1
sentinel is consumed.

Fixes opencv#4195
@Huxingyu

Copy link
Copy Markdown
Author

Hi @asmorkalov, this PR fixes #4195 (segfault in calcOpticalFlowSparseToDense when k exceeds the number of sparse matches). It clamps the effective neighbor count to min(k, match_num) per call without mutating the user's k, and rejects fewer than 3 matches/neighbors with a clear cv::Exception, plus regression tests.

This is my first contribution to opencv_contrib, so the CI workflow needs a maintainer to approve it before it will run. Could you approve the workflow when you have a moment? I've already built opencv_test_optflow/opencv_test_ximgproc locally (ASan) and all new tests plus the existing MultiThreadReproducibility suite pass.

@Huxingyu

Huxingyu commented Sep 1, 2026

Copy link
Copy Markdown
Author

Hi @asmorkalov,

All CI jobs have now completed. The failures appear to be existing baseline or infrastructure failures rather than regressions from this PR.

Most importantly, both test modules affected by this change pass on all four x86 Linux configurations:

  • Ubuntu 20.04: opencv_test_optflow and opencv_test_ximgproc passed
  • Ubuntu 22.04: opencv_test_optflow and opencv_test_ximgproc passed
  • Ubuntu 24.04: opencv_test_optflow and opencv_test_ximgproc passed
  • Ubuntu 26.04: opencv_test_optflow and opencv_test_ximgproc passed

The successful macOS, ARM64, and RISC-V jobs provide additional coverage.

The red checks are unrelated:

  • Windows fails before checkout because the self-hosted runner cannot find print_system_information.sh. The same failure is present in an unrelated run: https://github.com/opencv/opencv_contrib/actions/runs/33073351880/job/98521559744
  • CUDA fails in CornerHarris and CornerMinEigen with ApertureSize(0), following opencv commit 6e4c669be805: opencv/opencv@6e4c669
  • Ubuntu 20.04 and 22.04 fail in the existing OpenCL DualTVL1 performance sanity test. The same test fails with the same values in unrelated PR runs, including https://github.com/opencv/opencv_contrib/actions/runs/33073351880
  • Ubuntu 22.04 and 24.04 time out in opencv_test_shape on the same self-hosted runner, opencv-cn-lin2-x86-64.
  • Ubuntu 26.04 fails the unrelated CV_Quality_BRISQUE.multi_channel floating-point tolerance test. The identical failure was already present in an unrelated July run.

Could you please review the PR and confirm whether these unrelated checks can be treated as baseline failures? If a rerun is preferred, it would probably be more useful after the shared CI issues are repaired.

The PR-specific regression tests pass, and the change was also validated locally with ASan.

@Huxingyu Huxingyu closed this Sep 1, 2026
@Huxingyu Huxingyu reopened this Sep 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant