From d540476e31b080aa1f903ad20ec0426dd3838be7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Antoine=20Beaupr=C3=A9?= <anarcat@debian.org>
Date: Tue, 25 Apr 2017 20:10:20 -0400
Subject: [PATCH] fix stack overflow in HandleNode() (CVE-2017-5950)

simply set a hardcoded recursion limit to 2000 (inspired by Python's)
to avoid infinitely recursing into arbitrary data structures

assert() the depth. unsure if this is the right approach, but given
that HandleNode() is "void", I am not sure how else to return an
error. the problem with this approach of course is that it will still
crash the caller, unless they have proper exception handling in place.

Closes: #459
---
 src/singledocparser.cpp | 2 ++
 src/singledocparser.h   | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/src/singledocparser.cpp b/src/singledocparser.cpp
index a27c1c3b..1b4262ee 100644
--- a/src/singledocparser.cpp
+++ b/src/singledocparser.cpp
@@ -46,6 +46,8 @@ void SingleDocParser::HandleDocument(EventHandler& eventHandler) {
 }
 
 void SingleDocParser::HandleNode(EventHandler& eventHandler) {
+  assert(depth < depth_limit);
+  depth++;
   // 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 2b92067c..7046f1e2 100644
--- a/src/singledocparser.h
+++ b/src/singledocparser.h
@@ -51,6 +51,8 @@ class SingleDocParser : private noncopyable {
   anchor_t LookupAnchor(const Mark& mark, const std::string& name) const;
 
  private:
+  int depth = 0;
+  int depth_limit = 2000;
   Scanner& m_scanner;
   const Directives& m_directives;
   std::unique_ptr<CollectionStack> m_pCollectionStack;
