From de804e29c1133beeed4530f30d36a342184f68c5 Mon Sep 17 00:00:00 2001 From: zyppe <210hcl@gmail.com> Date: Thu, 29 Feb 2024 16:07:46 +0800 Subject: [PATCH] Initialize for yaml-cpp --- .gitignore | 1 + .yaml-cpp.metadata | 1 + cve-2018-20574.patch | 259 +++++++++++++++++++++++++++++++++++ yaml-cpp-CVE-2017-5950.patch | 82 +++++++++++ yaml-cpp-abi-breakage.patch | 16 +++ yaml-cpp.changes | 79 +++++++++++ yaml-cpp.spec | 89 ++++++++++++ 7 files changed, 527 insertions(+) create mode 100644 .gitignore create mode 100644 .yaml-cpp.metadata create mode 100644 cve-2018-20574.patch create mode 100644 yaml-cpp-CVE-2017-5950.patch create mode 100644 yaml-cpp-abi-breakage.patch create mode 100644 yaml-cpp.changes create mode 100644 yaml-cpp.spec diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e6c7cea --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +yaml-cpp-0.6.3.tar.gz diff --git a/.yaml-cpp.metadata b/.yaml-cpp.metadata new file mode 100644 index 0000000..51ae6a2 --- /dev/null +++ b/.yaml-cpp.metadata @@ -0,0 +1 @@ +c7e29865de70c54ee5f9ddef38abc5354d9a82b301bf07b93f623b230140c88d yaml-cpp-0.6.3.tar.gz diff --git a/cve-2018-20574.patch b/cve-2018-20574.patch new file mode 100644 index 0000000..e42fc54 --- /dev/null +++ b/cve-2018-20574.patch @@ -0,0 +1,259 @@ +--- + test/parser_test.cpp | 13 +++++++++++++ + 1 file changed, 19 insertions(+) + +Index: yaml-cpp-yaml-cpp-0.6.1/test/parser_test.cpp +=================================================================== +--- /dev/null ++++ yaml-cpp-yaml-cpp-0.6.1/test/parser_test.cpp +@@ -0,0 +1,54 @@ ++#include ++#include "yaml-cpp/parser.h" ++#include "yaml-cpp/exceptions.h" ++#include "mock_event_handler.h" ++#include "gtest/gtest.h" ++ ++using YAML::Parser; ++using YAML::MockEventHandler; ++using ::testing::NiceMock; ++ ++TEST(ParserTest, CVE_2017_5950) { ++ std::string excessive_recursion; ++ for (auto i = 0; i != 16384; ++i) ++ excessive_recursion.push_back('['); ++ std::istringstream input{excessive_recursion}; ++ Parser parser{input}; ++ ++ NiceMock handler; ++ EXPECT_THROW(parser.HandleNextDocument(handler), YAML::DeepRecursion); ++} ++ ++TEST(ParserTest, CVE_2018_20573) { ++ std::string excessive_recursion; ++ for (auto i = 0; i != 20535; ++i) ++ excessive_recursion.push_back('{'); ++ std::istringstream input{excessive_recursion}; ++ Parser parser{input}; ++ ++ NiceMock handler; ++ EXPECT_THROW(parser.HandleNextDocument(handler), YAML::DeepRecursion); ++} ++ ++TEST(ParserTest, CVE_2018_20574) { ++ std::string excessive_recursion; ++ for (auto i = 0; i != 21989; ++i) ++ excessive_recursion.push_back('{'); ++ std::istringstream input{excessive_recursion}; ++ Parser parser{input}; ++ ++ NiceMock handler; ++ EXPECT_THROW(parser.HandleNextDocument(handler), YAML::DeepRecursion); ++} ++ ++TEST(ParserTest, CVE_2019_6285) { ++ std::string excessive_recursion; ++ for (auto i = 0; i != 23100; ++i) ++ excessive_recursion.push_back('['); ++ excessive_recursion.push_back('f'); ++ std::istringstream input{excessive_recursion}; ++ Parser parser{input}; ++ ++ NiceMock handler; ++ EXPECT_THROW(parser.HandleNextDocument(handler), YAML::DeepRecursion); ++} +Index: yaml-cpp-yaml-cpp-0.6.1/include/yaml-cpp/depthguard.h +=================================================================== +--- /dev/null ++++ yaml-cpp-yaml-cpp-0.6.1/include/yaml-cpp/depthguard.h +@@ -0,0 +1,77 @@ ++#ifndef DEPTH_GUARD_H_00000000000000000000000000000000000000000000000000000000 ++#define DEPTH_GUARD_H_00000000000000000000000000000000000000000000000000000000 ++ ++#if defined(_MSC_VER) || \ ++ (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ ++ (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 ++#pragma once ++#endif ++ ++#include "exceptions.h" ++ ++namespace YAML { ++ ++/** ++ * @brief The DeepRecursion class ++ * An exception class which is thrown by DepthGuard. Ideally it should be ++ * a member of DepthGuard. However, DepthGuard is a templated class which means ++ * that any catch points would then need to know the template parameters. It is ++ * simpler for clients to not have to know at the catch point what was the ++ * maximum depth. ++ */ ++class DeepRecursion : public ParserException { ++public: ++ virtual ~DeepRecursion() = default; ++ ++ DeepRecursion(int depth, const Mark& mark_, const std::string& msg_); ++ ++ // Returns the recursion depth when the exception was thrown ++ int depth() const { ++ return m_depth; ++ } ++ ++private: ++ int m_depth = 0; ++}; ++ ++/** ++ * @brief The DepthGuard class ++ * DepthGuard takes a reference to an integer. It increments the integer upon ++ * construction of DepthGuard and decrements the integer upon destruction. ++ * ++ * If the integer would be incremented past max_depth, then an exception is ++ * thrown. This is ideally geared toward guarding against deep recursion. ++ * ++ * @param max_depth ++ * compile-time configurable maximum depth. ++ */ ++template ++class DepthGuard final { ++public: ++ DepthGuard(int & depth_, const Mark& mark_, const std::string& msg_) : m_depth(depth_) { ++ ++m_depth; ++ if ( max_depth <= m_depth ) { ++ throw DeepRecursion{m_depth, mark_, msg_}; ++ } ++ } ++ ++ DepthGuard(const DepthGuard & copy_ctor) = delete; ++ DepthGuard(DepthGuard && move_ctor) = delete; ++ DepthGuard & operator=(const DepthGuard & copy_assign) = delete; ++ DepthGuard & operator=(DepthGuard && move_assign) = delete; ++ ++ ~DepthGuard() { ++ --m_depth; ++ } ++ ++ int current_depth() const { ++ return m_depth; ++ } ++ ++private: ++ int & m_depth; ++}; ++ ++} // namespace YAML ++ ++#endif // DEPTH_GUARD_H_00000000000000000000000000000000000000000000000000000000 +Index: yaml-cpp-yaml-cpp-0.6.1/src/depthguard.cpp +=================================================================== +--- /dev/null ++++ yaml-cpp-yaml-cpp-0.6.1/src/depthguard.cpp +@@ -0,0 +1,10 @@ ++#include "yaml-cpp/depthguard.h" ++ ++namespace YAML { ++ ++DeepRecursion::DeepRecursion(int depth, const Mark& mark_, const std::string& msg_) ++ : ParserException(mark_, msg_), ++ m_depth(depth) { ++} ++ ++} // namespace YAML +Index: yaml-cpp-yaml-cpp-0.6.1/src/singledocparser.cpp +=================================================================== +--- yaml-cpp-yaml-cpp-0.6.1.orig/src/singledocparser.cpp ++++ yaml-cpp-yaml-cpp-0.6.1/src/singledocparser.cpp +@@ -7,6 +7,7 @@ + #include "singledocparser.h" + #include "tag.h" + #include "token.h" ++#include "yaml-cpp/depthguard.h" + #include "yaml-cpp/emitterstyle.h" + #include "yaml-cpp/eventhandler.h" + #include "yaml-cpp/exceptions.h" // IWYU pragma: keep +@@ -46,9 +47,8 @@ void SingleDocParser::HandleDocument(Eve + } + + void SingleDocParser::HandleNode(EventHandler& eventHandler) { +- if (depth > depth_limit) { +- throw ParserException(m_scanner.mark(), ErrorMsg::BAD_FILE); +- } ++ DepthGuard<2000> depthguard(depth, m_scanner.mark(), ErrorMsg::BAD_FILE); ++ + // an empty node *is* a possibility + if (m_scanner.empty()) { + eventHandler.OnNull(m_scanner.mark(), NullAnchor); +@@ -60,11 +60,9 @@ void SingleDocParser::HandleNode(EventHa + + // special case: a value node by itself must be a map, with no header + if (m_scanner.peek().type == Token::VALUE) { +- depth++; + eventHandler.OnMapStart(mark, "?", NullAnchor, EmitterStyle::Default); + HandleMap(eventHandler); + eventHandler.OnMapEnd(); +- depth--; + return; + } + +@@ -99,42 +97,32 @@ void SingleDocParser::HandleNode(EventHa + m_scanner.pop(); + return; + case Token::FLOW_SEQ_START: +- depth++; + eventHandler.OnSequenceStart(mark, tag, anchor, EmitterStyle::Flow); + HandleSequence(eventHandler); + eventHandler.OnSequenceEnd(); +- depth--; + return; + case Token::BLOCK_SEQ_START: +- depth++; + eventHandler.OnSequenceStart(mark, tag, anchor, EmitterStyle::Block); + HandleSequence(eventHandler); + eventHandler.OnSequenceEnd(); +- depth--; + return; + case Token::FLOW_MAP_START: +- depth++; + eventHandler.OnMapStart(mark, tag, anchor, EmitterStyle::Flow); + HandleMap(eventHandler); + eventHandler.OnMapEnd(); +- depth--; + return; + case Token::BLOCK_MAP_START: +- depth++; + eventHandler.OnMapStart(mark, tag, anchor, EmitterStyle::Block); + HandleMap(eventHandler); + eventHandler.OnMapEnd(); +- depth--; + return; + case Token::KEY: + // compact maps can only go in a flow sequence + if (m_pCollectionStack->GetCurCollectionType() == + CollectionType::FlowSeq) { +- depth++; + eventHandler.OnMapStart(mark, tag, anchor, EmitterStyle::Flow); + HandleMap(eventHandler); + eventHandler.OnMapEnd(); +- depth--; + return; + } + break; +Index: yaml-cpp-yaml-cpp-0.6.1/src/singledocparser.h +=================================================================== +--- yaml-cpp-yaml-cpp-0.6.1.orig/src/singledocparser.h ++++ yaml-cpp-yaml-cpp-0.6.1/src/singledocparser.h +@@ -16,6 +16,7 @@ + + namespace YAML { + class CollectionStack; ++template class DepthGuard; // depthguard.h + class EventHandler; + class Node; + class Scanner; +@@ -52,7 +53,6 @@ class SingleDocParser : private noncopya + + private: + int depth = 0; +- int depth_limit = 2048; + Scanner& m_scanner; + const Directives& m_directives; + std::unique_ptr m_pCollectionStack; diff --git a/yaml-cpp-CVE-2017-5950.patch b/yaml-cpp-CVE-2017-5950.patch new file mode 100644 index 0000000..3ca7524 --- /dev/null +++ b/yaml-cpp-CVE-2017-5950.patch @@ -0,0 +1,82 @@ +Index: yaml-cpp-yaml-cpp-0.6.1/src/singledocparser.cpp +=================================================================== +--- yaml-cpp-yaml-cpp-0.6.1.orig/src/singledocparser.cpp ++++ yaml-cpp-yaml-cpp-0.6.1/src/singledocparser.cpp +@@ -46,6 +46,9 @@ void SingleDocParser::HandleDocument(Eve + } + + void SingleDocParser::HandleNode(EventHandler& eventHandler) { ++ if (depth > depth_limit) { ++ throw ParserException(m_scanner.mark(), ErrorMsg::BAD_FILE); ++ } + // an empty node *is* a possibility + if (m_scanner.empty()) { + eventHandler.OnNull(m_scanner.mark(), NullAnchor); +@@ -57,9 +60,11 @@ void SingleDocParser::HandleNode(EventHa + + // special case: a value node by itself must be a map, with no header + if (m_scanner.peek().type == Token::VALUE) { ++ depth++; + eventHandler.OnMapStart(mark, "?", NullAnchor, EmitterStyle::Default); + HandleMap(eventHandler); + eventHandler.OnMapEnd(); ++ depth--; + return; + } + +@@ -94,32 +99,42 @@ void SingleDocParser::HandleNode(EventHa + m_scanner.pop(); + return; + case Token::FLOW_SEQ_START: ++ depth++; + eventHandler.OnSequenceStart(mark, tag, anchor, EmitterStyle::Flow); + HandleSequence(eventHandler); + eventHandler.OnSequenceEnd(); ++ depth--; + return; + case Token::BLOCK_SEQ_START: ++ depth++; + eventHandler.OnSequenceStart(mark, tag, anchor, EmitterStyle::Block); + HandleSequence(eventHandler); + eventHandler.OnSequenceEnd(); ++ depth--; + return; + case Token::FLOW_MAP_START: ++ depth++; + eventHandler.OnMapStart(mark, tag, anchor, EmitterStyle::Flow); + HandleMap(eventHandler); + eventHandler.OnMapEnd(); ++ depth--; + return; + case Token::BLOCK_MAP_START: ++ depth++; + eventHandler.OnMapStart(mark, tag, anchor, EmitterStyle::Block); + HandleMap(eventHandler); + eventHandler.OnMapEnd(); ++ depth--; + return; + case Token::KEY: + // compact maps can only go in a flow sequence + if (m_pCollectionStack->GetCurCollectionType() == + CollectionType::FlowSeq) { ++ depth++; + eventHandler.OnMapStart(mark, tag, anchor, EmitterStyle::Flow); + HandleMap(eventHandler); + eventHandler.OnMapEnd(); ++ depth--; + return; + } + break; +Index: yaml-cpp-yaml-cpp-0.6.1/src/singledocparser.h +=================================================================== +--- yaml-cpp-yaml-cpp-0.6.1.orig/src/singledocparser.h ++++ yaml-cpp-yaml-cpp-0.6.1/src/singledocparser.h +@@ -51,6 +51,8 @@ class SingleDocParser : private noncopya + anchor_t LookupAnchor(const Mark& mark, const std::string& name) const; + + private: ++ int depth = 0; ++ int depth_limit = 2048; + Scanner& m_scanner; + const Directives& m_directives; + std::unique_ptr m_pCollectionStack; diff --git a/yaml-cpp-abi-breakage.patch b/yaml-cpp-abi-breakage.patch new file mode 100644 index 0000000..dca2a86 --- /dev/null +++ b/yaml-cpp-abi-breakage.patch @@ -0,0 +1,16 @@ +Index: yaml-cpp-yaml-cpp-0.6.3/src/node_data.cpp +=================================================================== +--- yaml-cpp-yaml-cpp-0.6.3.orig/src/node_data.cpp ++++ yaml-cpp-yaml-cpp-0.6.3/src/node_data.cpp +@@ -17,6 +17,11 @@ const std::string& node_data::empty_scal + static const std::string svalue; + return svalue; + } ++extern "C" { ++// provides 0.6.1 ABI compatibility for: ++// std::string node_data::empty_scalar; ++std::string _ZN4YAML6detail9node_data12empty_scalarB5cxx11E; ++} + + node_data::node_data() + : m_isDefined(false), diff --git a/yaml-cpp.changes b/yaml-cpp.changes new file mode 100644 index 0000000..abf0a3f --- /dev/null +++ b/yaml-cpp.changes @@ -0,0 +1,79 @@ +* Thu Jul 14 2022 sbrabec@suse.com +- Version 0.6.3 changed ABI without changing SONAME. Re-add symbol + from the old ABI to prevent ABI breakage and crash of + applications compiled with 0.6.1 (bsc#1200624, bsc#1178332, + bsc#1178331, bsc#1160171, yaml-cpp-abi-breakage.patch). +* Sat Apr 9 2022 sbrabec@suse.com +- Fix CVE-2018-20573 The Scanner:EnsureTokensInQueue function in yaml-cpp + allows remote attackers to cause DOS via a crafted YAML file + (CVE-2018-20573, bsc#1121227) +- Fix CVE-2018-20574 The SingleDocParser:HandleFlowMap function in + yaml-cpp allows remote attackers to cause DOS via a crafted YAML file + (CVE-2018-20574, bsc#1121230) +- Fix CVE-2019-6285 The SingleDocParser::HandleFlowSequence function in + cpp allows remote attackers to cause DOS via a crafted YAML file + (CVE-2019-6285, bsc#1122004) +- Fix CVE-2019-6292 An issue was discovered in singledocparser.cpp in + yaml-cpp which cause DOS by stack consumption + (CVE-2019-6292, bsc#1122021) +- Added patch cve-2018-20574.patch +* Tue Dec 17 2019 mrostecki@opensuse.org +- Update to 0.6.3: + * bug fixes + * CMake updates, now requiring 3.1 +- Remove merged patch to fix PIE build: + * yaml-cpp-fix-pie.patch +* Thu Aug 9 2018 rpm@fthiessen.de +- Update to 0.6.2: + * Fix incorrect version numbering +* Wed Feb 14 2018 pmonrealgonzalez@suse.com +- Security fix: [bsc#1032144, CVE-2017-5950] + * Stack overflow in SingleDocParser::HandleNode() function + * Added patch yaml-cpp-CVE-2017-5950.patch +* Fri Feb 2 2018 tchvatal@suse.com +- Update to 0.6.1: + * Just brownpaperbag over previous release +* Wed Jan 31 2018 pmonrealgonzalez@suse.com +- Update to version 0.6.0 + * yaml-cpp no longer depends on Boost + * Requires C++11 + * Some bug fixes and performance improvements +- Dropped patch yaml-cpp-disable-bundled-gmock.patch since it can + be configured with the option YAML_CPP_BUILD_TESTS +* Thu Feb 2 2017 adam.majer@suse.de +- use individual libboost-*-devel packages instead of boost-devel +* Mon Jul 11 2016 tchvatal@suse.com +- Fix building with updated cmake and wrong -fPIE parsing: + * yaml-cpp-disable-bundled-gmock.patch + * yaml-cpp-fix-pie.patch +* Fri Feb 12 2016 mpluskal@suse.com +- Update to 0.5.3 + * Bugfix release. + * This will be the last release that does not require C++11. +- Drop upstreamed fix-node-regression.patch +- Small spec file cleanups +* Fri Nov 13 2015 tchvatal@suse.com +- Add patch to fix wrong node behaviour in 0.5.2 bnc#954749: + * fix-node-regression.patch +* Sat Aug 1 2015 rpm@fthiessen.de +- Update version 0.5.2 + * Some bugfixes +- Updated spec file + * Using cmake macro + * Updated copyright. +* Tue Jul 2 2013 asterios.dramis@gmail.com +- Added boost-devel in yaml-cpp-devel Requires: (some yaml-cpp headers require + boost headers). +* Sat Jun 29 2013 i@marguerite.su +- update version 0.5.1 + * a bug fix release for the new API +* Sun Jul 22 2012 i@marguerite.su +- fix sle builds. +* Sun Jul 22 2012 i@marguerite.su +- update version 0.3.0 + * minor bug fixing release +* Sat Jan 28 2012 jengelh@medozas.de +- Remove redundant tags/sections per specfile guideline suggestions +- Parallel building using %%_smp_mflags +* Mon Nov 14 2011 tchvatal@suse.com +- Initial commit of yaml-cpp. diff --git a/yaml-cpp.spec b/yaml-cpp.spec new file mode 100644 index 0000000..1b75f50 --- /dev/null +++ b/yaml-cpp.spec @@ -0,0 +1,89 @@ +# +# spec file for package yaml-cpp +# +# Copyright (c) 2022-2023 ZhuningOS +# + + +%define library_name libyaml-cpp0_6 +Name: yaml-cpp +Version: 0.6.3 +Release: 150400.4.3.1 +Summary: YAML parser and emitter in C++ +License: MIT +Group: Development/Libraries/C and C++ +URL: https://github.com/jbeder/yaml-cpp/ +Source: https://github.com/jbeder/yaml-cpp/archive/%{name}-%{version}.tar.gz +# PATCH-FIX-UPSTREAM bsc#1032144 CVE-2017-5950 Stack overflow in SingleDocParser::HandleNode() +Patch0: yaml-cpp-CVE-2017-5950.patch +# PATCH-FIX-UPSTREAM bsc#1121227 CVE-2018-20573 +# PATCH-FIX-UPSTREAM bsc#1121230 CVE-2018-20574 +# PATCH-FIX-UPSTREAM bsc#1122004 CVE-2019-6285 +# PATCH-FIX-UPSTREAM bsc#1122021 CVE-2019-6292 +Patch2: cve-2018-20574.patch +# PATCH-HACK-SUSE yaml-cpp-abi-breakage.patch bsc1200624 bsc1178332 bsc1178331 bsc1160171 sbrabec@suse.com -- Re-add symbol from the old ABI to prevent ABI breakage. +Patch3: yaml-cpp-abi-breakage.patch +BuildRequires: cmake +BuildRequires: pkgconfig +BuildRequires: sed +%if %{?suse_version} >= 1330 +BuildRequires: gcc +BuildRequires: gcc-c++ +%else +BuildRequires: gcc6 +BuildRequires: gcc6-c++ +%endif + +%description +A YAML parser and emitter in C++ matching the YAML 1.2 spec. + +%package -n %{library_name} +Summary: YAML parser and emitter in C++ +Group: Development/Libraries/C and C++ + +%description -n %{library_name} +A YAML parser and emitter in C++ matching the YAML 1.2 spec. + +%package devel +Summary: Development files for %{name} +Group: Development/Libraries/C and C++ +Requires: %{library_name} = %{version} + +%description devel +Development files for %{name} library. + +%prep +%autosetup -n %{name}-%{name}-%{version} -p1 + +%build +export CC=gcc +export CXX=g++ +%if 0%{?suse_version} < 1330 +export CC=gcc-6 +export CXX=g++-6 +%endif +%cmake \ + -DYAML_BUILD_SHARED_LIBS:BOOL=ON \ + -DYAML_CPP_BUILD_TESTS:BOOL=OFF \ + -DCMAKE_C_COMPILER=$CC \ + -DCMAKE_CXX_COMPILER=$CXX + +make %{?_smp_mflags} + +%install +%cmake_install + +%post -n %{library_name} -p /sbin/ldconfig +%postun -n %{library_name} -p /sbin/ldconfig + +%files -n %{library_name} +%license LICENSE +%{_libdir}/libyaml-cpp.so.* + +%files devel +%{_includedir}/yaml-cpp/ +%{_libdir}/libyaml-cpp.so +%{_libdir}/pkgconfig/yaml-cpp.pc +%{_libdir}/cmake/%{name}/ + +%changelog