You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
77 lines
2.2 KiB
77 lines
2.2 KiB
#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
|