summaryrefslogtreecommitdiff
path: root/dev-cpp/yaml-cpp/files/yaml-cpp-0.6.3-fix-overflows.patch
blob: 4c5418db22d343f72a6ab1f6761a4d7356dbbc01 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
This patch comes from the upstream commit here[1], slightly modified to
apply to 0.6.3. The pull request[2] mentions fixing CVE-2017-5950,
CVE-2018-{20573,20574}, and CVE-2019-6285. Note that CVE-2019-6292 appears to
be a duplicate of CVE-2019-6285 [3].

[1] https://github.com/jbeder/yaml-cpp/commit/4edff1fa5dbfca16fc72d89870841bee89f8ef89
[2] https://github.com/jbeder/yaml-cpp/pull/807
[3] https://github.com/jbeder/yaml-cpp/issues/660

diff --git a/include/yaml-cpp/depthguard.h b/include/yaml-cpp/depthguard.h
new file mode 100644
index 00000000..8ca61ac6
--- /dev/null
+++ b/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
diff --git a/src/depthguard.cpp b/src/depthguard.cpp
new file mode 100644
index 00000000..b88cd340
--- /dev/null
+++ b/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
diff --git a/src/singledocparser.cpp b/src/singledocparser.cpp
index 47e9e047..3e5638be 100644
--- a/src/singledocparser.cpp
+++ b/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
@@ -47,6 +48,8 @@ void SingleDocParser::HandleDocument(EventHandler& eventHandler) {
 }
 
 void SingleDocParser::HandleNode(EventHandler& eventHandler) {
+  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);
diff --git a/src/singledocparser.h b/src/singledocparser.h
index c8cfca9d..f484eb1f 100644
--- a/src/singledocparser.h
+++ b/src/singledocparser.h
@@ -15,6 +15,7 @@
 
 namespace YAML {
 class CollectionStack;
+template <int> class DepthGuard; // depthguard.h
 class EventHandler;
 class Node;
 class Scanner;
@@ -55,6 +56,7 @@ class SingleDocParser {
   anchor_t LookupAnchor(const Mark& mark, const std::string& name) const;
 
  private:
+  int depth = 0;
   Scanner& m_scanner;
   const Directives& m_directives;
   std::unique_ptr<CollectionStack> m_pCollectionStack;