Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-15:Update
yaml-cpp
cve-2018-20574.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File cve-2018-20574.patch of Package yaml-cpp
--- 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 <yaml-cpp/depthguard.h> +#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<MockEventHandler> 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<MockEventHandler> 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<MockEventHandler> 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<MockEventHandler> 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 <int max_depth = 2000> +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 <int> 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<CollectionStack> m_pCollectionStack;
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor