diff options
author | innokentii <innokentii@yandex-team.com> | 2023-03-23 17:02:27 +0300 |
---|---|---|
committer | innokentii <innokentii@yandex-team.com> | 2023-03-23 17:02:27 +0300 |
commit | 1b63dc868aaa1066fd2f723f739ea086a2a49601 (patch) | |
tree | f317d82984b0facf4a5d81720e5bb54cf9a124d4 | |
parent | 8007028c9d3043fe9909990721048e49127eeeec (diff) | |
download | ydb-1b63dc868aaa1066fd2f723f739ea086a2a49601.tar.gz |
Fix leaks on fyamlcpp misuse
fix possible leaks on misuse
-rw-r--r-- | library/cpp/yaml/fyamlcpp/fyamlcpp.cpp | 22 | ||||
-rw-r--r-- | library/cpp/yaml/fyamlcpp/fyamlcpp.h | 8 | ||||
-rw-r--r-- | library/cpp/yaml/fyamlcpp/fyamlcpp_ut.cpp | 67 |
3 files changed, 81 insertions, 16 deletions
diff --git a/library/cpp/yaml/fyamlcpp/fyamlcpp.cpp b/library/cpp/yaml/fyamlcpp/fyamlcpp.cpp index 9ab1465dfe..b8d8b17596 100644 --- a/library/cpp/yaml/fyamlcpp/fyamlcpp.cpp +++ b/library/cpp/yaml/fyamlcpp/fyamlcpp.cpp @@ -11,14 +11,6 @@ namespace NFyaml { const char* zstr = ""; -struct TStringHashT { - size_t operator()(const TString& str) const { - auto* ptr = str.empty() ? zstr : &str[0]; - return MurmurHash<size_t>(reinterpret_cast<char*>(&ptr), sizeof(ptr)); - } -}; - - enum class EErrorType { Debug = FYET_DEBUG, Info = FYET_INFO, @@ -295,8 +287,8 @@ TNode TNodeRef::Copy() const { TNode TNodeRef::Copy(TDocument& to) const { ENSURE_NODE_NOT_EMPTY(Node_); auto* fromDoc = fy_node_document(Node_); - auto& fromUserdata = *reinterpret_cast<THashSet<TString, TStringHashT>*>(fy_document_get_userdata(fromDoc)); - auto& toUserdata = *reinterpret_cast<THashSet<TString, TStringHashT>*>(fy_document_get_userdata(to.Document_.get())); + auto& fromUserdata = *reinterpret_cast<THashSet<TSimpleSharedPtr<TString>, TStringPtrHashT>*>(fy_document_get_userdata(fromDoc)); + auto& toUserdata = *reinterpret_cast<THashSet<TSimpleSharedPtr<TString>, TStringPtrHashT>*>(fy_document_get_userdata(to.Document_.get())); toUserdata.insert(fromUserdata.begin(), fromUserdata.end()); return TNode(fy_node_copy(to.Document_.get(), Node_)); } @@ -714,7 +706,7 @@ TDocument::TDocument(TString str, fy_document* doc, fy_diag* diag) : Document_(doc, fy_document_destroy) , Diag_(diag, fy_diag_destroy) { - auto* userdata = new THashSet<TString, TStringHashT>({str}); + auto* userdata = new THashSet<TSimpleSharedPtr<TString>, TStringPtrHashT>({MakeSimpleShared<TString>(std::move(str))}); fy_document_set_userdata(doc, userdata); fy_document_register_on_destroy(doc, &DestroyDocumentStrings); RegisterUserDataCleanup(); @@ -729,7 +721,7 @@ TDocument::TDocument(fy_document* doc, fy_diag* diag) TDocument TDocument::Parse(TString str) { - auto* cstr = str.empty() ? zstr : &str[0]; + const char* cstr = str.empty() ? zstr : str.cbegin(); fy_diag_cfg dcfg; fy_diag_cfg_default(&dcfg); std::unique_ptr<fy_diag, void(*)(fy_diag*)> diag(fy_diag_create(&dcfg), fy_diag_destroy); @@ -757,8 +749,8 @@ TDocument TDocument::Clone() const { fy_document* doc = fy_document_clone(Document_.get()); fy_document_set_userdata( doc, - new THashSet<TString, TStringHashT>( - *reinterpret_cast<THashSet<TString, TStringHashT>*>(fy_document_get_userdata(Document_.get())) + new THashSet<TSimpleSharedPtr<TString>, TStringPtrHashT>( + *reinterpret_cast<THashSet<TSimpleSharedPtr<TString>, TStringPtrHashT>*>(fy_document_get_userdata(Document_.get())) ) ); fy_document_register_on_destroy(doc, &DestroyDocumentStrings); @@ -879,7 +871,7 @@ TParser::TParser(TString rawStream, fy_parser* parser, fy_diag* diag) TParser TParser::Create(TString str) { - auto* stream = str.empty() ? zstr : &str[0]; + const char* stream = str.empty() ? zstr : str.cbegin(); fy_diag_cfg dcfg; fy_diag_cfg_default(&dcfg); std::unique_ptr<fy_diag, void(*)(fy_diag*)> diag(fy_diag_create(&dcfg), fy_diag_destroy); diff --git a/library/cpp/yaml/fyamlcpp/fyamlcpp.h b/library/cpp/yaml/fyamlcpp/fyamlcpp.h index c1ec03d25f..bcf9362d73 100644 --- a/library/cpp/yaml/fyamlcpp/fyamlcpp.h +++ b/library/cpp/yaml/fyamlcpp/fyamlcpp.h @@ -18,6 +18,12 @@ struct fy_node_pair; namespace NFyaml { +struct TStringPtrHashT { + size_t operator()(const TSimpleSharedPtr<TString>& str) const { + return (size_t)str.Get(); + } +}; + struct TFyamlEx : public yexception {}; enum class ENodeType { @@ -589,7 +595,7 @@ private: static void DestroyDocumentStrings(fy_document *fyd, void *user) { Y_UNUSED(fyd); if (user) { - auto* data = reinterpret_cast<THashSet<TString>*>(user); + auto* data = reinterpret_cast<THashSet<TSimpleSharedPtr<TString>, TStringPtrHashT>*>(user); delete data; } } diff --git a/library/cpp/yaml/fyamlcpp/fyamlcpp_ut.cpp b/library/cpp/yaml/fyamlcpp/fyamlcpp_ut.cpp index 94093c4157..ffe1d4368c 100644 --- a/library/cpp/yaml/fyamlcpp/fyamlcpp_ut.cpp +++ b/library/cpp/yaml/fyamlcpp/fyamlcpp_ut.cpp @@ -86,4 +86,71 @@ test: b auto docOpt3 = parser.NextDocument(); UNIT_ASSERT(!docOpt3); } + + Y_UNIT_TEST(Leak) { + std::optional<NFyaml::TDocument> doc; + + { + std::optional<NFyaml::TDocument> item1; + std::optional<NFyaml::TDocument> item2; + { + const TString items = R"( +item: + x: 1 + y: 2 +--- +test: + a: noop + b: + - 1 + - 2 + - 3 +--- +x: b +)"; + auto parser = NFyaml::TParser::Create(items); + + item1.emplace(*parser.NextDocument()); + item2.emplace(*parser.NextDocument()); + parser.NextDocument(); + parser.NextDocument(); + } + + { + const TString config = R"( +test: a +--- +test: [] +--- +x: b +)"; + auto parser = NFyaml::TParser::Create(config); + + parser.NextDocument(); + doc.emplace(*parser.NextDocument()); + parser.NextDocument(); + parser.NextDocument(); + } + + { + auto item1NodeRef = item1->Root().Map().at("item"); + auto item2NodeRef = item2->Root().Map().at("test"); + auto docNodeRef = doc->Root().Map().at("test"); + auto node1 = item1NodeRef.Copy(*doc); + auto node2 = item2NodeRef.Copy(*doc); + docNodeRef.Sequence().Append(node1.Ref()); + docNodeRef.Sequence().Append(node2.Ref()); + item1.reset(); + item2.reset(); + } + } + + auto seq = doc->Root().Map().at("test").Sequence(); + UNIT_ASSERT_VALUES_EQUAL(seq[0].Map().at("x").Scalar(), "1"); + UNIT_ASSERT_VALUES_EQUAL(seq[0].Map().at("y").Scalar(), "2"); + UNIT_ASSERT_VALUES_EQUAL(seq[1].Map().at("a").Scalar(), "noop"); + UNIT_ASSERT_VALUES_EQUAL(seq[1].Map().at("b").Sequence().at(0).Scalar(), "1"); + UNIT_ASSERT_VALUES_EQUAL(seq[1].Map().at("b").Sequence().at(1).Scalar(), "2"); + UNIT_ASSERT_VALUES_EQUAL(seq[1].Map().at("b").Sequence().at(2).Scalar(), "3"); + } } |