Merge pull request #17877 from alalek:issue_17876

pull/17878/head
Alexander Alekhin 4 years ago
commit 8a480ac3c1
  1. 8
      modules/core/include/opencv2/core/persistence.hpp
  2. 40
      modules/core/src/persistence.cpp
  3. 23
      modules/core/test/test_io.cpp

@ -510,6 +510,8 @@ public:
@param fs Pointer to the file storage structure. @param fs Pointer to the file storage structure.
@param blockIdx Index of the memory block where the file node is stored @param blockIdx Index of the memory block where the file node is stored
@param ofs Offset in bytes from the beginning of the serialized storage @param ofs Offset in bytes from the beginning of the serialized storage
@deprecated
*/ */
FileNode(const FileStorage* fs, size_t blockIdx, size_t ofs); FileNode(const FileStorage* fs, size_t blockIdx, size_t ofs);
@ -614,7 +616,9 @@ public:
CV_WRAP Mat mat() const; CV_WRAP Mat mat() const;
//protected: //protected:
const FileStorage* fs; FileNode(FileStorage::Impl* fs, size_t blockIdx, size_t ofs);
FileStorage::Impl* fs;
size_t blockIdx; size_t blockIdx;
size_t ofs; size_t ofs;
}; };
@ -679,7 +683,7 @@ public:
bool equalTo(const FileNodeIterator& it) const; bool equalTo(const FileNodeIterator& it) const;
protected: protected:
const FileStorage* fs; FileStorage::Impl* fs;
size_t blockIdx; size_t blockIdx;
size_t ofs; size_t ofs;
size_t blockSize; size_t blockSize;

@ -1376,9 +1376,9 @@ public:
return new_ptr; return new_ptr;
} }
unsigned getStringOfs( const std::string& key ) unsigned getStringOfs( const std::string& key ) const
{ {
str_hash_t::iterator it = str_hash.find(key); str_hash_t::const_iterator it = str_hash.find(key);
return it != str_hash.end() ? it->second : 0; return it != str_hash.end() ? it->second : 0;
} }
@ -1468,7 +1468,7 @@ public:
writeInt(ptr, (int)rawSize); writeInt(ptr, (int)rawSize);
} }
void normalizeNodeOfs(size_t& blockIdx, size_t& ofs) void normalizeNodeOfs(size_t& blockIdx, size_t& ofs) const
{ {
while( ofs >= fs_data_blksz[blockIdx] ) while( ofs >= fs_data_blksz[blockIdx] )
{ {
@ -2048,18 +2048,24 @@ FileStorage& operator << (FileStorage& fs, const String& str)
FileNode::FileNode() FileNode::FileNode()
: fs(NULL)
{ {
fs = 0;
blockIdx = ofs = 0; blockIdx = ofs = 0;
} }
FileNode::FileNode(const FileStorage* _fs, size_t _blockIdx, size_t _ofs) FileNode::FileNode(FileStorage::Impl* _fs, size_t _blockIdx, size_t _ofs)
: fs(_fs)
{ {
fs = _fs;
blockIdx = _blockIdx; blockIdx = _blockIdx;
ofs = _ofs; ofs = _ofs;
} }
FileNode::FileNode(const FileStorage* _fs, size_t _blockIdx, size_t _ofs)
: FileNode(_fs->p.get(), _blockIdx, _ofs)
{
// nothing
}
FileNode::FileNode(const FileNode& node) FileNode::FileNode(const FileNode& node)
{ {
fs = node.fs; fs = node.fs;
@ -2082,7 +2088,7 @@ FileNode FileNode::operator[](const std::string& nodename) const
CV_Assert( isMap() ); CV_Assert( isMap() );
unsigned key = fs->p->getStringOfs(nodename); unsigned key = fs->getStringOfs(nodename);
size_t i, sz = size(); size_t i, sz = size();
FileNodeIterator it = begin(); FileNodeIterator it = begin();
@ -2091,7 +2097,7 @@ FileNode FileNode::operator[](const std::string& nodename) const
FileNode n = *it; FileNode n = *it;
const uchar* p = n.ptr(); const uchar* p = n.ptr();
unsigned key2 = (unsigned)readInt(p + 1); unsigned key2 = (unsigned)readInt(p + 1);
CV_Assert( key2 < fs->p->str_hash_data.size() ); CV_Assert( key2 < fs->str_hash_data.size() );
if( key == key2 ) if( key == key2 )
return n; return n;
} }
@ -2167,7 +2173,7 @@ std::string FileNode::name() const
if(!p) if(!p)
return std::string(); return std::string();
size_t nameofs = p[1] | (p[2]<<8) | (p[3]<<16) | (p[4]<<24); size_t nameofs = p[1] | (p[2]<<8) | (p[3]<<16) | (p[4]<<24);
return fs->p->getName(nameofs); return fs->getName(nameofs);
} }
FileNode::operator int() const FileNode::operator int() const
@ -2292,12 +2298,12 @@ size_t FileNode::rawSize() const
uchar* FileNode::ptr() uchar* FileNode::ptr()
{ {
return !fs ? 0 : (uchar*)fs->p->getNodePtr(blockIdx, ofs); return !fs ? 0 : (uchar*)fs->getNodePtr(blockIdx, ofs);
} }
const uchar* FileNode::ptr() const const uchar* FileNode::ptr() const
{ {
return !fs ? 0 : fs->p->getNodePtr(blockIdx, ofs); return !fs ? 0 : fs->getNodePtr(blockIdx, ofs);
} }
void FileNode::setValue( int type, const void* value, int len ) void FileNode::setValue( int type, const void* value, int len )
@ -2328,7 +2334,7 @@ void FileNode::setValue( int type, const void* value, int len )
else else
CV_Error(Error::StsNotImplemented, "Only scalar types can be dynamically assigned to a file node"); CV_Error(Error::StsNotImplemented, "Only scalar types can be dynamically assigned to a file node");
p = fs->p->reserveNodeSpace(*this, sz); p = fs->reserveNodeSpace(*this, sz);
*p++ = (uchar)(type | (tag & NAMED)); *p++ = (uchar)(type | (tag & NAMED));
if( tag & NAMED ) if( tag & NAMED )
p += 4; p += 4;
@ -2402,8 +2408,8 @@ FileNodeIterator::FileNodeIterator( const FileNode& node, bool seekEnd )
idx = nodeNElems; idx = nodeNElems;
} }
} }
fs->p->normalizeNodeOfs(blockIdx, ofs); fs->normalizeNodeOfs(blockIdx, ofs);
blockSize = fs->p->fs_data_blksz[blockIdx]; blockSize = fs->fs_data_blksz[blockIdx];
} }
} }
@ -2430,7 +2436,7 @@ FileNodeIterator& FileNodeIterator::operator=(const FileNodeIterator& it)
FileNode FileNodeIterator::operator *() const FileNode FileNodeIterator::operator *() const
{ {
return FileNode(idx < nodeNElems ? fs : 0, blockIdx, ofs); return FileNode(idx < nodeNElems ? fs : NULL, blockIdx, ofs);
} }
FileNodeIterator& FileNodeIterator::operator ++ () FileNodeIterator& FileNodeIterator::operator ++ ()
@ -2442,8 +2448,8 @@ FileNodeIterator& FileNodeIterator::operator ++ ()
ofs += n.rawSize(); ofs += n.rawSize();
if( ofs >= blockSize ) if( ofs >= blockSize )
{ {
fs->p->normalizeNodeOfs(blockIdx, ofs); fs->normalizeNodeOfs(blockIdx, ofs);
blockSize = fs->p->fs_data_blksz[blockIdx]; blockSize = fs->fs_data_blksz[blockIdx];
} }
return *this; return *this;
} }

@ -1788,4 +1788,27 @@ TEST(Core_InputOutput, FileStorage_copy_constructor_17412)
EXPECT_EQ(0, remove(fname.c_str())); EXPECT_EQ(0, remove(fname.c_str()));
} }
TEST(Core_InputOutput, FileStorage_copy_constructor_17412_heap)
{
std::string fname = tempfile("test.yml");
FileStorage fs_orig(fname, cv::FileStorage::WRITE);
fs_orig << "string" << "wat";
fs_orig.release();
// no crash anymore
cv::FileStorage fs;
// use heap to allow valgrind detections
{
cv::FileStorage* fs2 = new cv::FileStorage(fname, cv::FileStorage::READ);
fs = *fs2;
delete fs2;
}
std::string s;
fs["string"] >> s;
EXPECT_EQ(s, "wat");
EXPECT_EQ(0, remove(fname.c_str()));
}
}} // namespace }} // namespace

Loading…
Cancel
Save