Merge pull request #19045 from alalek:issue_17553

* flann: avoid dangling pointers on lost features data

* flann: fix Index::load()
pull/19087/head
Alexander Alekhin 4 years ago committed by GitHub
parent 8ac304517e
commit a04479746a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      modules/features2d/test/test_nearestneighbors.cpp
  2. 3
      modules/flann/include/opencv2/flann/miniflann.hpp
  3. 25
      modules/flann/src/miniflann.cpp

@ -123,7 +123,7 @@ void NearestNeighborTest::run( int /*start_from*/ ) {
Mat desc( featuresCount, dims, CV_32FC1 ); Mat desc( featuresCount, dims, CV_32FC1 );
ts->get_rng().fill( desc, RNG::UNIFORM, minValue, maxValue ); ts->get_rng().fill( desc, RNG::UNIFORM, minValue, maxValue );
createModel( desc ); createModel( desc.clone() ); // .clone() is used to simulate dangling pointers problem: https://github.com/opencv/opencv/issues/17553
tempCode = checkGetPoints( desc ); tempCode = checkGetPoints( desc );
if( tempCode != cvtest::TS::OK ) if( tempCode != cvtest::TS::OK )

@ -169,10 +169,13 @@ public:
CV_WRAP cvflann::flann_algorithm_t getAlgorithm() const; CV_WRAP cvflann::flann_algorithm_t getAlgorithm() const;
protected: protected:
bool load_(const String& filename);
cvflann::flann_distance_t distType; cvflann::flann_distance_t distType;
cvflann::flann_algorithm_t algo; cvflann::flann_algorithm_t algo;
int featureType; int featureType;
void* index; void* index;
Mat features_clone; // index may store features pointer internally for searching, so avoid dangling pointers: https://github.com/opencv/opencv/issues/17553
}; };
} } // namespace cv::flann } } // namespace cv::flann

@ -390,14 +390,18 @@ void Index::build(InputArray _data, const IndexParams& params, flann_distance_t
CV_INSTRUMENT_REGION(); CV_INSTRUMENT_REGION();
release(); release();
// Index may reuse 'data' during search, need to keep it alive
features_clone = _data.getMat().clone();
Mat data = features_clone;
algo = getParam<flann_algorithm_t>(params, "algorithm", FLANN_INDEX_LINEAR); algo = getParam<flann_algorithm_t>(params, "algorithm", FLANN_INDEX_LINEAR);
if( algo == FLANN_INDEX_SAVED ) if( algo == FLANN_INDEX_SAVED )
{ {
load(_data, getParam<String>(params, "filename", String())); load_(getParam<String>(params, "filename", String()));
return; return;
} }
Mat data = _data.getMat();
index = 0; index = 0;
featureType = data.type(); featureType = data.type();
distType = _distType; distType = _distType;
@ -462,6 +466,8 @@ void Index::release()
{ {
CV_INSTRUMENT_REGION(); CV_INSTRUMENT_REGION();
features_clone.release();
if( !index ) if( !index )
return; return;
@ -785,9 +791,20 @@ bool loadIndex(Index* index0, void*& index, const Mat& data, FILE* fin, const Di
bool Index::load(InputArray _data, const String& filename) bool Index::load(InputArray _data, const String& filename)
{ {
Mat data = _data.getMat();
bool ok = true;
release(); release();
// Index may reuse 'data' during search, need to keep it alive
features_clone = _data.getMat().clone();
Mat data = features_clone;
return load_(filename);
}
bool Index::load_(const String& filename)
{
Mat data = features_clone;
bool ok = true;
FILE* fin = fopen(filename.c_str(), "rb"); FILE* fin = fopen(filename.c_str(), "rb");
if (fin == NULL) if (fin == NULL)
return false; return false;

Loading…
Cancel
Save