aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs/3rdparty/yaml-cpp/include/yaml-cpp/depthguard.h
blob: 8ca61ac6ccc175fc557d3e3a203ed72fe0387b9e (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
#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