提交 7f6dcc27 编写于 作者: A Alexander Alekhin

Merge pull request #21467 from alalek:issue_21448

...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
#include <unordered_map> #include <unordered_map>
#include <iterator> #include <iterator>
#include <opencv2/core/utils/logger.hpp>
namespace cv namespace cv
{ {
...@@ -499,21 +501,29 @@ bool FileStorage::Impl::open(const char *filename_or_buf, int _flags, const char ...@@ -499,21 +501,29 @@ bool FileStorage::Impl::open(const char *filename_or_buf, int _flags, const char
if (!isGZ) { if (!isGZ) {
file = fopen(filename.c_str(), !write_mode ? "rt" : !append ? "wt" : "a+t"); file = fopen(filename.c_str(), !write_mode ? "rt" : !append ? "wt" : "a+t");
if (!file) if (!file)
{
CV_LOG_ERROR(NULL, "Can't open file: '" << filename << "' in " << (!write_mode ? "read" : !append ? "write" : "append") << " mode");
return false; return false;
}
} else { } else {
#if USE_ZLIB #if USE_ZLIB
char mode[] = {write_mode ? 'w' : 'r', 'b', compression ? compression : '3', '\0'}; char mode[] = {write_mode ? 'w' : 'r', 'b', compression ? compression : '3', '\0'};
gzfile = gzopen(filename.c_str(), mode); gzfile = gzopen(filename.c_str(), mode);
if (!gzfile) if (!gzfile)
{
CV_LOG_ERROR(NULL, "Can't open archive: '" << filename << "' mode=" << mode);
return false; return false;
}
#else #else
CV_Error(cv::Error::StsNotImplemented, "There is no compressed file storage support in this configuration"); CV_Error(cv::Error::StsNotImplemented, "There is no compressed file storage support in this configuration");
#endif #endif
} }
} }
// FIXIT release() must do that, use CV_Assert() here instead
roots.clear(); roots.clear();
fs_data.clear(); fs_data.clear();
wrap_margin = 71; wrap_margin = 71;
fmt = FileStorage::FORMAT_AUTO; fmt = FileStorage::FORMAT_AUTO;
...@@ -616,14 +626,14 @@ bool FileStorage::Impl::open(const char *filename_or_buf, int _flags, const char ...@@ -616,14 +626,14 @@ bool FileStorage::Impl::open(const char *filename_or_buf, int _flags, const char
puts("\n"); puts("\n");
} }
emitter = createXMLEmitter(this); emitter_do_not_use_direct_dereference = createXMLEmitter(this);
} else if (fmt == FileStorage::FORMAT_YAML) { } else if (fmt == FileStorage::FORMAT_YAML) {
if (!append) if (!append)
puts("%YAML:1.0\n---\n"); puts("%YAML:1.0\n---\n");
else else
puts("...\n---\n"); puts("...\n---\n");
emitter = createYAMLEmitter(this); emitter_do_not_use_direct_dereference = createYAMLEmitter(this);
} else { } else {
CV_Assert(fmt == FileStorage::FORMAT_JSON); CV_Assert(fmt == FileStorage::FORMAT_JSON);
if (!append) if (!append)
...@@ -653,7 +663,7 @@ bool FileStorage::Impl::open(const char *filename_or_buf, int _flags, const char ...@@ -653,7 +663,7 @@ bool FileStorage::Impl::open(const char *filename_or_buf, int _flags, const char
} }
} }
write_stack.back().indent = 4; write_stack.back().indent = 4;
emitter = createJSONEmitter(this); emitter_do_not_use_direct_dereference = createJSONEmitter(this);
} }
is_opened = true; is_opened = true;
} else { } else {
...@@ -701,20 +711,20 @@ bool FileStorage::Impl::open(const char *filename_or_buf, int _flags, const char ...@@ -701,20 +711,20 @@ bool FileStorage::Impl::open(const char *filename_or_buf, int _flags, const char
switch (fmt) { switch (fmt) {
case FileStorage::FORMAT_XML: case FileStorage::FORMAT_XML:
parser = createXMLParser(this); parser_do_not_use_direct_dereference = createXMLParser(this);
break; break;
case FileStorage::FORMAT_YAML: case FileStorage::FORMAT_YAML:
parser = createYAMLParser(this); parser_do_not_use_direct_dereference = createYAMLParser(this);
break; break;
case FileStorage::FORMAT_JSON: case FileStorage::FORMAT_JSON:
parser = createJSONParser(this); parser_do_not_use_direct_dereference = createJSONParser(this);
break; break;
default: default:
parser = Ptr<FileStorageParser>(); parser_do_not_use_direct_dereference = Ptr<FileStorageParser>();
} }
if (!parser.empty()) { if (!parser_do_not_use_direct_dereference.empty()) {
ok = parser->parse(ptr); ok = getParser().parse(ptr);
if (ok) { if (ok) {
finalizeCollection(root_nodes); finalizeCollection(root_nodes);
...@@ -728,7 +738,9 @@ bool FileStorage::Impl::open(const char *filename_or_buf, int _flags, const char ...@@ -728,7 +738,9 @@ bool FileStorage::Impl::open(const char *filename_or_buf, int _flags, const char
} }
} }
} }
catch (...) { catch (...)
{
// FIXIT log error message
is_opened = true; is_opened = true;
release(); release();
throw; throw;
...@@ -926,7 +938,7 @@ void FileStorage::Impl::endWriteStruct() { ...@@ -926,7 +938,7 @@ void FileStorage::Impl::endWriteStruct() {
if (fmt == FileStorage::FORMAT_JSON && !FileNode::isFlow(current_struct.flags) && write_stack.size() > 1) if (fmt == FileStorage::FORMAT_JSON && !FileNode::isFlow(current_struct.flags) && write_stack.size() > 1)
current_struct.indent = write_stack[write_stack.size() - 2].indent; current_struct.indent = write_stack[write_stack.size() - 2].indent;
emitter->endWriteStruct(current_struct); getEmitter().endWriteStruct(current_struct);
write_stack.pop_back(); write_stack.pop_back();
if (!write_stack.empty()) if (!write_stack.empty())
...@@ -945,7 +957,7 @@ void FileStorage::Impl::startWriteStruct_helper(const char *key, int struct_flag ...@@ -945,7 +957,7 @@ void FileStorage::Impl::startWriteStruct_helper(const char *key, int struct_flag
if (type_name && type_name[0] == '\0') if (type_name && type_name[0] == '\0')
type_name = 0; type_name = 0;
FStructData s = emitter->startWriteStruct(write_stack.back(), key, struct_flags, type_name); FStructData s = getEmitter().startWriteStruct(write_stack.back(), key, struct_flags, type_name);
write_stack.push_back(s); write_stack.push_back(s);
size_t write_stack_size = write_stack.size(); size_t write_stack_size = write_stack.size();
...@@ -956,7 +968,7 @@ void FileStorage::Impl::startWriteStruct_helper(const char *key, int struct_flag ...@@ -956,7 +968,7 @@ void FileStorage::Impl::startWriteStruct_helper(const char *key, int struct_flag
flush(); flush();
if (fmt == FileStorage::FORMAT_JSON && type_name && type_name[0] && FileNode::isMap(struct_flags)) { if (fmt == FileStorage::FORMAT_JSON && type_name && type_name[0] && FileNode::isMap(struct_flags)) {
emitter->write("type_id", type_name, false); getEmitter().write("type_id", type_name, false);
} }
} }
...@@ -997,7 +1009,7 @@ void FileStorage::Impl::startWriteStruct(const char *key, int struct_flags, ...@@ -997,7 +1009,7 @@ void FileStorage::Impl::startWriteStruct(const char *key, int struct_flags,
void FileStorage::Impl::writeComment(const char *comment, bool eol_comment) { void FileStorage::Impl::writeComment(const char *comment, bool eol_comment) {
CV_Assert(write_mode); CV_Assert(write_mode);
emitter->writeComment(comment, eol_comment); getEmitter().writeComment(comment, eol_comment);
} }
void FileStorage::Impl::startNextStream() { void FileStorage::Impl::startNextStream() {
...@@ -1006,7 +1018,7 @@ void FileStorage::Impl::startNextStream() { ...@@ -1006,7 +1018,7 @@ void FileStorage::Impl::startNextStream() {
while (!write_stack.empty()) while (!write_stack.empty())
endWriteStruct(); endWriteStruct();
flush(); flush();
emitter->startNextStream(); getEmitter().startNextStream();
empty_stream = true; empty_stream = true;
write_stack.push_back(FStructData("", FileNode::EMPTY, 0)); write_stack.push_back(FStructData("", FileNode::EMPTY, 0));
bufofs = 0; bufofs = 0;
...@@ -1015,17 +1027,17 @@ void FileStorage::Impl::startNextStream() { ...@@ -1015,17 +1027,17 @@ void FileStorage::Impl::startNextStream() {
void FileStorage::Impl::write(const String &key, int value) { void FileStorage::Impl::write(const String &key, int value) {
CV_Assert(write_mode); CV_Assert(write_mode);
emitter->write(key.c_str(), value); getEmitter().write(key.c_str(), value);
} }
void FileStorage::Impl::write(const String &key, double value) { void FileStorage::Impl::write(const String &key, double value) {
CV_Assert(write_mode); CV_Assert(write_mode);
emitter->write(key.c_str(), value); getEmitter().write(key.c_str(), value);
} }
void FileStorage::Impl::write(const String &key, const String &value) { void FileStorage::Impl::write(const String &key, const String &value) {
CV_Assert(write_mode); CV_Assert(write_mode);
emitter->write(key.c_str(), value.c_str(), false); getEmitter().write(key.c_str(), value.c_str(), false);
} }
void FileStorage::Impl::writeRawData(const std::string &dt, const void *_data, size_t len) { void FileStorage::Impl::writeRawData(const std::string &dt, const void *_data, size_t len) {
...@@ -1111,7 +1123,7 @@ void FileStorage::Impl::writeRawData(const std::string &dt, const void *_data, s ...@@ -1111,7 +1123,7 @@ void FileStorage::Impl::writeRawData(const std::string &dt, const void *_data, s
return; return;
} }
emitter->writeScalar(0, ptr); getEmitter().writeScalar(0, ptr);
} }
offset = (int) (data - data0); offset = (int) (data - data0);
...@@ -1597,8 +1609,8 @@ FileStorage::Impl::Base64Decoder::Base64Decoder() { ...@@ -1597,8 +1609,8 @@ FileStorage::Impl::Base64Decoder::Base64Decoder() {
eos = true; eos = true;
} }
void FileStorage::Impl::Base64Decoder::init(Ptr<FileStorageParser> &_parser, char *_ptr, int _indent) { void FileStorage::Impl::Base64Decoder::init(const Ptr<FileStorageParser> &_parser, char *_ptr, int _indent) {
parser = _parser; parser_do_not_use_direct_dereference = _parser;
ptr = _ptr; ptr = _ptr;
indent = _indent; indent = _indent;
encoded.clear(); encoded.clear();
...@@ -1641,9 +1653,9 @@ bool FileStorage::Impl::Base64Decoder::readMore(int needed) { ...@@ -1641,9 +1653,9 @@ bool FileStorage::Impl::Base64Decoder::readMore(int needed) {
decoded.resize(sz); decoded.resize(sz);
ofs = 0; ofs = 0;
CV_Assert(!parser.empty() && ptr); CV_Assert(ptr);
char *beg = 0, *end = 0; char *beg = 0, *end = 0;
bool ok = parser->getBase64Row(ptr, indent, beg, end); bool ok = getParser().getBase64Row(ptr, indent, beg, end);
ptr = end; ptr = end;
std::copy(beg, end, std::back_inserter(encoded)); std::copy(beg, end, std::back_inserter(encoded));
totalchars += end - beg; totalchars += end - beg;
...@@ -1730,7 +1742,7 @@ char *FileStorage::Impl::Base64Decoder::getPtr() const { return ptr; } ...@@ -1730,7 +1742,7 @@ char *FileStorage::Impl::Base64Decoder::getPtr() const { return ptr; }
char *FileStorage::Impl::parseBase64(char *ptr, int indent, FileNode &collection) { char *FileStorage::Impl::parseBase64(char *ptr, int indent, FileNode &collection) {
const int BASE64_HDR_SIZE = 24; const int BASE64_HDR_SIZE = 24;
char dt[BASE64_HDR_SIZE + 1] = {0}; char dt[BASE64_HDR_SIZE + 1] = {0};
base64decoder.init(parser, ptr, indent); base64decoder.init(parser_do_not_use_direct_dereference, ptr, indent);
int i, k; int i, k;
......
...@@ -139,7 +139,7 @@ public: ...@@ -139,7 +139,7 @@ public:
{ {
public: public:
Base64Decoder(); Base64Decoder();
void init(Ptr<FileStorageParser>& _parser, char* _ptr, int _indent); void init(const Ptr<FileStorageParser>& _parser, char* _ptr, int _indent);
bool readMore(int needed); bool readMore(int needed);
...@@ -155,7 +155,13 @@ public: ...@@ -155,7 +155,13 @@ public:
char* getPtr() const; char* getPtr() const;
protected: protected:
Ptr<FileStorageParser> parser; Ptr<FileStorageParser> parser_do_not_use_direct_dereference;
FileStorageParser& getParser() const
{
if (!parser_do_not_use_direct_dereference)
CV_Error(Error::StsNullPtr, "Parser is not available");
return *parser_do_not_use_direct_dereference;
}
char* ptr; char* ptr;
int indent; int indent;
std::vector<char> encoded; std::vector<char> encoded;
...@@ -205,8 +211,20 @@ public: ...@@ -205,8 +211,20 @@ public:
std::deque<char> outbuf; std::deque<char> outbuf;
Ptr<FileStorageEmitter> emitter; Ptr<FileStorageEmitter> emitter_do_not_use_direct_dereference;
Ptr<FileStorageParser> parser; FileStorageEmitter& getEmitter()
{
if (!emitter_do_not_use_direct_dereference)
CV_Error(Error::StsNullPtr, "Emitter is not available");
return *emitter_do_not_use_direct_dereference;
}
Ptr<FileStorageParser> parser_do_not_use_direct_dereference;
FileStorageParser& getParser() const
{
if (!parser_do_not_use_direct_dereference)
CV_Error(Error::StsNullPtr, "Parser is not available");
return *parser_do_not_use_direct_dereference;
}
Base64Decoder base64decoder; Base64Decoder base64decoder;
base64::Base64Writer* base64_writer; base64::Base64Writer* base64_writer;
...@@ -228,4 +246,4 @@ public: ...@@ -228,4 +246,4 @@ public:
} }
#endif #endif
\ No newline at end of file
...@@ -1918,5 +1918,29 @@ TEST(Core_InputOutput, FileStorage_16F_json) ...@@ -1918,5 +1918,29 @@ TEST(Core_InputOutput, FileStorage_16F_json)
test_20279(fs); test_20279(fs);
} }
TEST(Core_InputOutput, FileStorage_invalid_path_regression_21448_YAML)
{
FileStorage fs("invalid_path/test.yaml", cv::FileStorage::WRITE);
EXPECT_FALSE(fs.isOpened());
EXPECT_ANY_THROW(fs.write("K", 1));
fs.release();
}
TEST(Core_InputOutput, FileStorage_invalid_path_regression_21448_XML)
{
FileStorage fs("invalid_path/test.xml", cv::FileStorage::WRITE);
EXPECT_FALSE(fs.isOpened());
EXPECT_ANY_THROW(fs.write("K", 1));
fs.release();
}
TEST(Core_InputOutput, FileStorage_invalid_path_regression_21448_JSON)
{
FileStorage fs("invalid_path/test.json", cv::FileStorage::WRITE);
EXPECT_FALSE(fs.isOpened());
EXPECT_ANY_THROW(fs.write("K", 1));
fs.release();
}
}} // namespace }} // namespace
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册