CVE-2019-19624
Description
An out-of-bounds read was discovered in OpenCV before 4.1.1. Specifically, variable coarsest_scale is assumed to be greater than or equal to finest_scale within the calc()/ocl_calc() functions in dis_flow.cpp. However, this is not true when dealing with small images, leading to an out-of-bounds read of the heap-allocated arrays Ux and Uy.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
OpenCV before 4.1.1 has an out-of-bounds read in DISOpticalFlow due to incorrect scale assumptions for small images, potentially leading to information disclosure.
Vulnerability
Details
An out-of-bounds read vulnerability exists in OpenCV versions prior to 4.1.1 within the calc() and ocl_calc() functions of dis_flow.cpp. The root cause is an incorrect assumption that the variable coarsest_scale is always greater than or equal to finest_scale. When processing small images, this assumption fails, leading to an out-of-bounds read of the heap-allocated arrays Ux and Uy [1][3].
Exploitation
Exploitation requires an attacker to supply a crafted small image to an application that uses OpenCV's DISOpticalFlow algorithm. No authentication is needed if the application processes untrusted images, and the attack can be triggered remotely if the application accepts image inputs over a network [1][3].
Impact
A successful out-of-bounds read can result in the disclosure of heap memory contents, potentially leaking sensitive information. The vulnerability does not directly enable code execution, but information leakage may aid further attacks [1][3].
Mitigation
The issue was fixed in OpenCV version 4.1.1 via commit d1615ba, which introduced functions autoSelectCoarsestScale and autoSelectPatchSizeAndScales to properly handle small images. Users are advised to update to OpenCV 4.1.1 or later [4].
AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
opencv-pythonPyPI | < 4.1.0.25 | 4.1.0.25 |
opencv-python-headlessPyPI | < 4.1.0.25 | 4.1.0.25 |
opencv-contrib-pythonPyPI | < 4.1.0.25 | 4.1.0.25 |
opencv-contrib-python-headlessPyPI | < 4.1.0.25 | 4.1.0.25 |
Affected products
5- OpenCV/OpenCVdescription
- ghsa-coords4 versionspkg:pypi/opencv-contrib-pythonpkg:pypi/opencv-contrib-python-headlesspkg:pypi/opencv-pythonpkg:pypi/opencv-python-headless
< 4.1.0.25+ 3 more
- (no CPE)range: < 4.1.0.25
- (no CPE)range: < 4.1.0.25
- (no CPE)range: < 4.1.0.25
- (no CPE)range: < 4.1.0.25
Patches
1d1615ba11a93video:fixed DISOpticalFlow segfault from small img
2 files changed · +93 −2
modules/video/src/dis_flow.cpp+65 −2 modified@@ -140,6 +140,8 @@ class DISOpticalFlowImpl CV_FINAL : public DISOpticalFlow void prepareBuffers(Mat &I0, Mat &I1, Mat &flow, bool use_flow); void precomputeStructureTensor(Mat &dst_I0xx, Mat &dst_I0yy, Mat &dst_I0xy, Mat &dst_I0x, Mat &dst_I0y, Mat &I0x, Mat &I0y); + int autoSelectCoarsestScale(int img_width); + void autoSelectPatchSizeAndScales(int img_width); struct PatchInverseSearch_ParBody : public ParallelLoopBody { @@ -435,6 +437,44 @@ void DISOpticalFlowImpl::precomputeStructureTensor(Mat &dst_I0xx, Mat &dst_I0yy, } } +int DISOpticalFlowImpl::autoSelectCoarsestScale(int img_width) +{ + const int fratio = 5; + return std::max(0, (int)std::floor(log2((2.0f*(float)img_width) / ((float)fratio * (float)patch_size)))); +} + +void DISOpticalFlowImpl::autoSelectPatchSizeAndScales(int img_width) +{ + switch (finest_scale) + { + case 1: + patch_size = 8; + coarsest_scale = autoSelectCoarsestScale(img_width); + finest_scale = std::max(coarsest_scale-2, 0); + break; + + case 3: + patch_size = 12; + coarsest_scale = autoSelectCoarsestScale(img_width); + finest_scale = std::max(coarsest_scale-4, 0); + break; + + case 4: + patch_size = 12; + coarsest_scale = autoSelectCoarsestScale(img_width); + finest_scale = std::max(coarsest_scale-5, 0); + break; + + // default case, fall-through. + case 2: + default: + patch_size = 8; + coarsest_scale = autoSelectCoarsestScale(img_width); + finest_scale = std::max(coarsest_scale-2, 0); + break; + } +} + DISOpticalFlowImpl::PatchInverseSearch_ParBody::PatchInverseSearch_ParBody(DISOpticalFlowImpl &_dis, int _nstripes, int _hs, Mat &dst_Sx, Mat &dst_Sy, Mat &src_Ux, Mat &src_Uy, Mat &_I0, Mat &_I1, @@ -1318,9 +1358,20 @@ bool DISOpticalFlowImpl::ocl_calc(InputArray I0, InputArray I1, InputOutputArray else flow.create(I1Mat.size(), CV_32FC2); UMat &u_flowMat = flow.getUMatRef(); - coarsest_scale = min((int)(log(max(I0Mat.cols, I0Mat.rows) / (4.0 * patch_size)) / log(2.0) + 0.5), /* Original code serach for maximal movement of width/4 */ + coarsest_scale = min((int)(log(max(I0Mat.cols, I0Mat.rows) / (4.0 * patch_size)) / log(2.0) + 0.5), /* Original code search for maximal movement of width/4 */ (int)(log(min(I0Mat.cols, I0Mat.rows) / patch_size) / log(2.0))); /* Deepest pyramid level greater or equal than patch*/ + if (coarsest_scale<0) + CV_Error(cv::Error::StsBadSize, "The input image must have either width or height >= 12"); + + if (coarsest_scale<finest_scale) + { + // choose the finest level based on coarsest level. + // Refs: https://github.com/tikroeger/OF_DIS/blob/2c9f2a674f3128d3a41c10e41cc9f3a35bb1b523/run_dense.cpp#L239 + int original_img_width = I0.size().width; + autoSelectPatchSizeAndScales(original_img_width); + } + ocl_prepareBuffers(I0Mat, I1Mat, u_flowMat, use_input_flow); u_Ux[coarsest_scale].setTo(0.0f); u_Uy[coarsest_scale].setTo(0.0f); @@ -1385,8 +1436,20 @@ void DISOpticalFlowImpl::calc(InputArray I0, InputArray I1, InputOutputArray flo else flow.create(I1Mat.size(), CV_32FC2); Mat flowMat = flow.getMat(); - coarsest_scale = min((int)(log(max(I0Mat.cols, I0Mat.rows) / (4.0 * patch_size)) / log(2.0) + 0.5), /* Original code serach for maximal movement of width/4 */ + coarsest_scale = min((int)(log(max(I0Mat.cols, I0Mat.rows) / (4.0 * patch_size)) / log(2.0) + 0.5), /* Original code search for maximal movement of width/4 */ (int)(log(min(I0Mat.cols, I0Mat.rows) / patch_size) / log(2.0))); /* Deepest pyramid level greater or equal than patch*/ + + if (coarsest_scale<0) + CV_Error(cv::Error::StsBadSize, "The input image must have either width or height >= 12"); + + if (coarsest_scale<finest_scale) + { + // choose the finest level based on coarsest level. + // Refs: https://github.com/tikroeger/OF_DIS/blob/2c9f2a674f3128d3a41c10e41cc9f3a35bb1b523/run_dense.cpp#L239 + int original_img_width = I0.size().width; + autoSelectPatchSizeAndScales(original_img_width); + } + int num_stripes = getNumThreads(); prepareBuffers(I0Mat, I1Mat, flowMat, use_input_flow);
modules/video/test/test_OF_accuracy.cpp+28 −0 modified@@ -121,6 +121,34 @@ TEST(DenseOpticalFlow_DIS, ReferenceAccuracy) } } +TEST(DenseOpticalFlow_DIS, InvalidImgSize_CoarsestLevelLessThanZero) +{ + cv::Ptr<cv::DISOpticalFlow> of = cv::DISOpticalFlow::create(); + const int mat_size = 10; + + cv::Mat x(mat_size, mat_size, CV_8UC1, 42); + cv::Mat y(mat_size, mat_size, CV_8UC1, 42); + cv::Mat flow; + + ASSERT_THROW(of->calc(x, y, flow), cv::Exception); +} + +// make sure that autoSelectPatchSizeAndScales() works properly. +TEST(DenseOpticalFlow_DIS, InvalidImgSize_CoarsestLevelLessThanFinestLevel) +{ + cv::Ptr<cv::DISOpticalFlow> of = cv::DISOpticalFlow::create(); + const int mat_size = 80; + + cv::Mat x(mat_size, mat_size, CV_8UC1, 42); + cv::Mat y(mat_size, mat_size, CV_8UC1, 42); + cv::Mat flow; + + of->calc(x, y, flow); + + ASSERT_EQ(flow.rows, mat_size); + ASSERT_EQ(flow.cols, mat_size); +} + TEST(DenseOpticalFlow_VariationalRefinement, ReferenceAccuracy) { Mat frame1, frame2, GT;
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
6- github.com/advisories/GHSA-jggw-2q6g-c3m6ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2019-19624ghsaADVISORY
- access.redhat.com/security/cve/cve-2019-19624ghsaWEB
- github.com/opencv/opencv-python/releases/tag/25ghsaWEB
- github.com/opencv/opencv/commit/d1615ba11a93062b1429fce9f0f638d1572d3418ghsax_refsource_MISCWEB
- github.com/opencv/opencv/issues/14554ghsax_refsource_MISCWEB
News mentions
0No linked articles in our index yet.