diff --git a/include/picojson/picojson.h b/include/picojson/picojson.h index ef4b903d8..76742fe06 100644 --- a/include/picojson/picojson.h +++ b/include/picojson/picojson.h @@ -110,6 +110,7 @@ extern "C" { #pragma warning(disable : 4244) // conversion from int to char #pragma warning(disable : 4127) // conditional expression is constant #pragma warning(disable : 4702) // unreachable code +#pragma warning(disable : 4706) // assignment within conditional expression #else #define SNPRINTF snprintf #endif @@ -129,7 +130,7 @@ enum { #endif }; -enum { INDENT_WIDTH = 2 }; +enum { INDENT_WIDTH = 2, DEFAULT_MAX_DEPTHS = 100 }; struct null {}; @@ -383,7 +384,7 @@ GET(array, *u_.array_) GET(object, *u_.object_) #ifdef PICOJSON_USE_INT64 GET(double, - (type_ == int64_type && (const_cast(this)->type_ = number_type, const_cast(this)->u_.number_ = u_.int64_), + (type_ == int64_type && (const_cast(this)->type_ = number_type, (const_cast(this)->u_.number_ = u_.int64_)), u_.number_)) GET(int64_t, u_.int64_) #else @@ -838,7 +839,7 @@ template inline bool _parse_object(Context &ct return false; } if (in.expect('}')) { - return true; + return ctx.parse_object_stop(); } do { std::string key; @@ -849,7 +850,7 @@ template inline bool _parse_object(Context &ct return false; } } while (in.expect(',')); - return in.expect('}'); + return in.expect('}') && ctx.parse_object_stop(); } template inline std::string _parse_number(input &in) { @@ -965,9 +966,10 @@ class deny_parse_context { class default_parse_context { protected: value *out_; + size_t depths_; public: - default_parse_context(value *out) : out_(out) { + default_parse_context(value *out, size_t depths = DEFAULT_MAX_DEPTHS) : out_(out), depths_(depths) { } bool set_null() { *out_ = value(); @@ -992,27 +994,37 @@ class default_parse_context { return _parse_string(out_->get(), in); } bool parse_array_start() { + if (depths_ == 0) + return false; + --depths_; *out_ = value(array_type, false); return true; } template bool parse_array_item(input &in, size_t) { array &a = out_->get(); a.push_back(value()); - default_parse_context ctx(&a.back()); + default_parse_context ctx(&a.back(), depths_); return _parse(ctx, in); } bool parse_array_stop(size_t) { + ++depths_; return true; } bool parse_object_start() { + if (depths_ == 0) + return false; *out_ = value(object_type, false); return true; } template bool parse_object_item(input &in, const std::string &key) { object &o = out_->get(); - default_parse_context ctx(&o[key]); + default_parse_context ctx(&o[key], depths_); return _parse(ctx, in); } + bool parse_object_stop() { + ++depths_; + return true; + } private: default_parse_context(const default_parse_context &); @@ -1020,6 +1032,9 @@ class default_parse_context { }; class null_parse_context { +protected: + size_t depths_; + public: struct dummy_str { void push_back(int) { @@ -1027,7 +1042,7 @@ class null_parse_context { }; public: - null_parse_context() { + null_parse_context(size_t depths = DEFAULT_MAX_DEPTHS) : depths_(depths) { } bool set_null() { return true; @@ -1048,20 +1063,31 @@ class null_parse_context { return _parse_string(s, in); } bool parse_array_start() { + if (depths_ == 0) + return false; + --depths_; return true; } template bool parse_array_item(input &in, size_t) { return _parse(*this, in); } bool parse_array_stop(size_t) { + ++depths_; return true; } bool parse_object_start() { + if (depths_ == 0) + return false; + --depths_; return true; } template bool parse_object_item(input &in, const std::string &) { + ++depths_; return _parse(*this, in); } + bool parse_object_stop() { + return true; + } private: null_parse_context(const null_parse_context &);