Skip to content

Commit 8a480ac

Browse files
committed
Merge pull request opencv#17877 from alalek:issue_17876
2 parents a199d7a + ffe0d50 commit 8a480ac

File tree

3 files changed

+52
-19
lines changed

3 files changed

+52
-19
lines changed

modules/core/include/opencv2/core/persistence.hpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,8 @@ class CV_EXPORTS_W_SIMPLE FileNode
510510
@param fs Pointer to the file storage structure.
511511
@param blockIdx Index of the memory block where the file node is stored
512512
@param ofs Offset in bytes from the beginning of the serialized storage
513+
514+
@deprecated
513515
*/
514516
FileNode(const FileStorage* fs, size_t blockIdx, size_t ofs);
515517

@@ -614,7 +616,9 @@ class CV_EXPORTS_W_SIMPLE FileNode
614616
CV_WRAP Mat mat() const;
615617

616618
//protected:
617-
const FileStorage* fs;
619+
FileNode(FileStorage::Impl* fs, size_t blockIdx, size_t ofs);
620+
621+
FileStorage::Impl* fs;
618622
size_t blockIdx;
619623
size_t ofs;
620624
};
@@ -679,7 +683,7 @@ class CV_EXPORTS FileNodeIterator
679683
bool equalTo(const FileNodeIterator& it) const;
680684

681685
protected:
682-
const FileStorage* fs;
686+
FileStorage::Impl* fs;
683687
size_t blockIdx;
684688
size_t ofs;
685689
size_t blockSize;

modules/core/src/persistence.cpp

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1376,9 +1376,9 @@ class FileStorage::Impl : public FileStorage_API
13761376
return new_ptr;
13771377
}
13781378

1379-
unsigned getStringOfs( const std::string& key )
1379+
unsigned getStringOfs( const std::string& key ) const
13801380
{
1381-
str_hash_t::iterator it = str_hash.find(key);
1381+
str_hash_t::const_iterator it = str_hash.find(key);
13821382
return it != str_hash.end() ? it->second : 0;
13831383
}
13841384

@@ -1468,7 +1468,7 @@ class FileStorage::Impl : public FileStorage_API
14681468
writeInt(ptr, (int)rawSize);
14691469
}
14701470

1471-
void normalizeNodeOfs(size_t& blockIdx, size_t& ofs)
1471+
void normalizeNodeOfs(size_t& blockIdx, size_t& ofs) const
14721472
{
14731473
while( ofs >= fs_data_blksz[blockIdx] )
14741474
{
@@ -2048,18 +2048,24 @@ FileStorage& operator << (FileStorage& fs, const String& str)
20482048

20492049

20502050
FileNode::FileNode()
2051+
: fs(NULL)
20512052
{
2052-
fs = 0;
20532053
blockIdx = ofs = 0;
20542054
}
20552055

2056-
FileNode::FileNode(const FileStorage* _fs, size_t _blockIdx, size_t _ofs)
2056+
FileNode::FileNode(FileStorage::Impl* _fs, size_t _blockIdx, size_t _ofs)
2057+
: fs(_fs)
20572058
{
2058-
fs = _fs;
20592059
blockIdx = _blockIdx;
20602060
ofs = _ofs;
20612061
}
20622062

2063+
FileNode::FileNode(const FileStorage* _fs, size_t _blockIdx, size_t _ofs)
2064+
: FileNode(_fs->p.get(), _blockIdx, _ofs)
2065+
{
2066+
// nothing
2067+
}
2068+
20632069
FileNode::FileNode(const FileNode& node)
20642070
{
20652071
fs = node.fs;
@@ -2082,7 +2088,7 @@ FileNode FileNode::operator[](const std::string& nodename) const
20822088

20832089
CV_Assert( isMap() );
20842090

2085-
unsigned key = fs->p->getStringOfs(nodename);
2091+
unsigned key = fs->getStringOfs(nodename);
20862092
size_t i, sz = size();
20872093
FileNodeIterator it = begin();
20882094

@@ -2091,7 +2097,7 @@ FileNode FileNode::operator[](const std::string& nodename) const
20912097
FileNode n = *it;
20922098
const uchar* p = n.ptr();
20932099
unsigned key2 = (unsigned)readInt(p + 1);
2094-
CV_Assert( key2 < fs->p->str_hash_data.size() );
2100+
CV_Assert( key2 < fs->str_hash_data.size() );
20952101
if( key == key2 )
20962102
return n;
20972103
}
@@ -2167,7 +2173,7 @@ std::string FileNode::name() const
21672173
if(!p)
21682174
return std::string();
21692175
size_t nameofs = p[1] | (p[2]<<8) | (p[3]<<16) | (p[4]<<24);
2170-
return fs->p->getName(nameofs);
2176+
return fs->getName(nameofs);
21712177
}
21722178

21732179
FileNode::operator int() const
@@ -2292,12 +2298,12 @@ size_t FileNode::rawSize() const
22922298

22932299
uchar* FileNode::ptr()
22942300
{
2295-
return !fs ? 0 : (uchar*)fs->p->getNodePtr(blockIdx, ofs);
2301+
return !fs ? 0 : (uchar*)fs->getNodePtr(blockIdx, ofs);
22962302
}
22972303

22982304
const uchar* FileNode::ptr() const
22992305
{
2300-
return !fs ? 0 : fs->p->getNodePtr(blockIdx, ofs);
2306+
return !fs ? 0 : fs->getNodePtr(blockIdx, ofs);
23012307
}
23022308

23032309
void FileNode::setValue( int type, const void* value, int len )
@@ -2328,7 +2334,7 @@ void FileNode::setValue( int type, const void* value, int len )
23282334
else
23292335
CV_Error(Error::StsNotImplemented, "Only scalar types can be dynamically assigned to a file node");
23302336

2331-
p = fs->p->reserveNodeSpace(*this, sz);
2337+
p = fs->reserveNodeSpace(*this, sz);
23322338
*p++ = (uchar)(type | (tag & NAMED));
23332339
if( tag & NAMED )
23342340
p += 4;
@@ -2402,8 +2408,8 @@ FileNodeIterator::FileNodeIterator( const FileNode& node, bool seekEnd )
24022408
idx = nodeNElems;
24032409
}
24042410
}
2405-
fs->p->normalizeNodeOfs(blockIdx, ofs);
2406-
blockSize = fs->p->fs_data_blksz[blockIdx];
2411+
fs->normalizeNodeOfs(blockIdx, ofs);
2412+
blockSize = fs->fs_data_blksz[blockIdx];
24072413
}
24082414
}
24092415

@@ -2430,7 +2436,7 @@ FileNodeIterator& FileNodeIterator::operator=(const FileNodeIterator& it)
24302436

24312437
FileNode FileNodeIterator::operator *() const
24322438
{
2433-
return FileNode(idx < nodeNElems ? fs : 0, blockIdx, ofs);
2439+
return FileNode(idx < nodeNElems ? fs : NULL, blockIdx, ofs);
24342440
}
24352441

24362442
FileNodeIterator& FileNodeIterator::operator ++ ()
@@ -2442,8 +2448,8 @@ FileNodeIterator& FileNodeIterator::operator ++ ()
24422448
ofs += n.rawSize();
24432449
if( ofs >= blockSize )
24442450
{
2445-
fs->p->normalizeNodeOfs(blockIdx, ofs);
2446-
blockSize = fs->p->fs_data_blksz[blockIdx];
2451+
fs->normalizeNodeOfs(blockIdx, ofs);
2452+
blockSize = fs->fs_data_blksz[blockIdx];
24472453
}
24482454
return *this;
24492455
}

modules/core/test/test_io.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1788,4 +1788,27 @@ TEST(Core_InputOutput, FileStorage_copy_constructor_17412)
17881788
EXPECT_EQ(0, remove(fname.c_str()));
17891789
}
17901790

1791+
TEST(Core_InputOutput, FileStorage_copy_constructor_17412_heap)
1792+
{
1793+
std::string fname = tempfile("test.yml");
1794+
FileStorage fs_orig(fname, cv::FileStorage::WRITE);
1795+
fs_orig << "string" << "wat";
1796+
fs_orig.release();
1797+
1798+
// no crash anymore
1799+
cv::FileStorage fs;
1800+
1801+
// use heap to allow valgrind detections
1802+
{
1803+
cv::FileStorage* fs2 = new cv::FileStorage(fname, cv::FileStorage::READ);
1804+
fs = *fs2;
1805+
delete fs2;
1806+
}
1807+
1808+
std::string s;
1809+
fs["string"] >> s;
1810+
EXPECT_EQ(s, "wat");
1811+
EXPECT_EQ(0, remove(fname.c_str()));
1812+
}
1813+
17911814
}} // namespace

0 commit comments

Comments
 (0)