Skip to content
This repository was archived by the owner on Aug 2, 2022. It is now read-only.

Commit f86a4b5

Browse files
committed
porting json/variant fixes from bitshares #3539
1 parent d7dff4f commit f86a4b5

File tree

12 files changed

+476
-355
lines changed

12 files changed

+476
-355
lines changed

libraries/fc/include/fc/exception/exception.hpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -123,17 +123,17 @@ namespace fc
123123
*/
124124
virtual std::shared_ptr<exception> dynamic_copy_exception()const;
125125

126-
friend void to_variant( const exception& e, variant& v );
127-
friend void from_variant( const variant& e, exception& ll );
126+
friend void to_variant( const exception& e, variant& v, uint32_t max_depth );
127+
friend void from_variant( const variant& e, exception& ll, uint32_t max_depth );
128128

129129
exception& operator=( const exception& copy );
130130
exception& operator=( exception&& copy );
131131
protected:
132132
std::unique_ptr<detail::exception_impl> my;
133133
};
134134

135-
void to_variant( const exception& e, variant& v );
136-
void from_variant( const variant& e, exception& ll );
135+
void to_variant( const exception& e, variant& v, uint32_t max_depth );
136+
void from_variant( const variant& e, exception& ll, uint32_t max_depth );
137137
typedef std::shared_ptr<exception> exception_ptr;
138138

139139
typedef optional<exception> oexception;

libraries/fc/include/fc/filesystem.hpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,8 @@ namespace fc {
182182
const fc::path& current_path();
183183

184184
class variant;
185-
void to_variant( const fc::path&, fc::variant& );
186-
void from_variant( const fc::variant& , fc::path& );
185+
void to_variant( const fc::path&, fc::variant&, uint32_t max_depth );
186+
void from_variant( const fc::variant& , fc::path&, uint32_t max_depth );
187187

188188
template<> struct get_typename<path> { static const char* name() { return "path"; } };
189189

libraries/fc/include/fc/io/json.hpp

+26-20
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
#include <fc/variant.hpp>
33
#include <fc/filesystem.hpp>
44

5+
#define DEFAULT_MAX_RECURSION_DEPTH 200
6+
57
namespace fc
68
{
79
using std::ostream;
@@ -28,49 +30,53 @@ namespace fc
2830
};
2931

3032
static ostream& to_stream( ostream& out, const fc::string&);
31-
static ostream& to_stream( ostream& out, const variant& v, output_formatting format = stringify_large_ints_and_doubles );
32-
static ostream& to_stream( ostream& out, const variants& v, output_formatting format = stringify_large_ints_and_doubles );
33-
static ostream& to_stream( ostream& out, const variant_object& v, output_formatting format = stringify_large_ints_and_doubles );
33+
static ostream& to_stream( ostream& out, const variant& v, output_formatting format = stringify_large_ints_and_doubles, uint32_t max_depth = DEFAULT_MAX_RECURSION_DEPTH );
34+
static ostream& to_stream( ostream& out, const variants& v, output_formatting format = stringify_large_ints_and_doubles, uint32_t max_depth = DEFAULT_MAX_RECURSION_DEPTH );
35+
static ostream& to_stream( ostream& out, const variant_object& v, output_formatting format = stringify_large_ints_and_doubles, uint32_t max_depth = DEFAULT_MAX_RECURSION_DEPTH );
36+
37+
//XXX static variant from_stream( buffered_istream& in, parse_type ptype = legacy_parser, uint32_t max_depth = DEFAULT_MAX_RECURSION_DEPTH );
3438

35-
static variant from_string( const string& utf8_str, parse_type ptype = legacy_parser );
36-
static variants variants_from_string( const string& utf8_str, parse_type ptype = legacy_parser );
37-
static string to_string( const variant& v, output_formatting format = stringify_large_ints_and_doubles );
38-
static string to_pretty_string( const variant& v, output_formatting format = stringify_large_ints_and_doubles );
39+
static variant from_string( const string& utf8_str, parse_type ptype = legacy_parser, uint32_t max_depth = DEFAULT_MAX_RECURSION_DEPTH );
40+
static variants variants_from_string( const string& utf8_str, parse_type ptype = legacy_parser, uint32_t max_depth = DEFAULT_MAX_RECURSION_DEPTH );
41+
static string to_string( const variant& v, output_formatting format = stringify_large_ints_and_doubles, uint32_t max_depth = DEFAULT_MAX_RECURSION_DEPTH );
42+
static string to_pretty_string( const variant& v, output_formatting format = stringify_large_ints_and_doubles, uint32_t max_depth = DEFAULT_MAX_RECURSION_DEPTH );
3943

40-
static bool is_valid( const std::string& json_str, parse_type ptype = legacy_parser );
44+
static bool is_valid( const std::string& json_str, parse_type ptype = legacy_parser, uint32_t max_depth = DEFAULT_MAX_RECURSION_DEPTH );
4145

4246
template<typename T>
43-
static void save_to_file( const T& v, const fc::path& fi, bool pretty = true, output_formatting format = stringify_large_ints_and_doubles )
47+
static void save_to_file( const T& v, const fc::path& fi, bool pretty = true, output_formatting format = stringify_large_ints_and_doubles, uint32_t max_depth = DEFAULT_MAX_RECURSION_DEPTH )
4448
{
45-
save_to_file( variant(v), fi, pretty, format );
49+
save_to_file( variant(v, max_depth), fi, pretty, format, max_depth );
4650
}
4751

48-
static void save_to_file( const variant& v, const fc::path& fi, bool pretty = true, output_formatting format = stringify_large_ints_and_doubles );
49-
static variant from_file( const fc::path& p, parse_type ptype = legacy_parser );
52+
static void save_to_file( const variant& v, const fc::path& fi, bool pretty = true, output_formatting format = stringify_large_ints_and_doubles, uint32_t max_depth = DEFAULT_MAX_RECURSION_DEPTH );
53+
static variant from_file( const fc::path& p, parse_type ptype = legacy_parser, uint32_t max_depth = DEFAULT_MAX_RECURSION_DEPTH );
5054

5155
template<typename T>
52-
static T from_file( const fc::path& p, parse_type ptype = legacy_parser )
56+
static T from_file( const fc::path& p, parse_type ptype = legacy_parser, uint32_t max_depth = DEFAULT_MAX_RECURSION_DEPTH )
5357
{
54-
return json::from_file(p, ptype).as<T>();
58+
return json::from_file(p, ptype, max_depth).as<T>();
5559
}
5660

5761
template<typename T>
58-
static string to_string( const T& v, output_formatting format = stringify_large_ints_and_doubles )
62+
static string to_string( const T& v, output_formatting format = stringify_large_ints_and_doubles, uint32_t max_depth = DEFAULT_MAX_RECURSION_DEPTH )
5963
{
60-
return to_string( variant(v), format );
64+
return to_string( variant(v, max_depth), format, max_depth );
6165
}
6266

6367
template<typename T>
64-
static string to_pretty_string( const T& v, output_formatting format = stringify_large_ints_and_doubles )
68+
static string to_pretty_string( const T& v, output_formatting format = stringify_large_ints_and_doubles, uint32_t max_depth = DEFAULT_MAX_RECURSION_DEPTH )
6569
{
66-
return to_pretty_string( variant(v), format );
70+
return to_pretty_string( variant(v, max_depth), format, max_depth );
6771
}
6872

6973
template<typename T>
70-
static void save_to_file( const T& v, const std::string& p, bool pretty = true, output_formatting format = stringify_large_ints_and_doubles )
74+
static void save_to_file( const T& v, const std::string& p, bool pretty = true, output_formatting format = stringify_large_ints_and_doubles, uint32_t max_depth = DEFAULT_MAX_RECURSION_DEPTH )
7175
{
72-
save_to_file( variant(v), fc::path(p), pretty );
76+
save_to_file( variant(v, max_depth), fc::path(p), pretty, format, max_depth );
7377
}
7478
};
7579

7680
} // fc
81+
82+
#undef DEFAULT_MAX_RECURSION_DEPTH

libraries/fc/include/fc/io/json_relaxed.hpp

+9-9
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
namespace fc { namespace json_relaxed
2222
{
2323
template<typename T, bool strict>
24-
variant variant_from_stream( T& in );
24+
variant variant_from_stream( T& in, uint32_t max_depth );
2525

2626
template<typename T>
2727
std::string tokenFromStream( T& in )
@@ -562,7 +562,7 @@ namespace fc { namespace json_relaxed
562562
} FC_CAPTURE_AND_RETHROW( (token) ) }
563563

564564
template<typename T, bool strict>
565-
variant_object objectFromStream( T& in )
565+
variant_object objectFromStream( T& in, uint32_t max_depth )
566566
{
567567
mutable_variant_object obj;
568568
try
@@ -590,7 +590,7 @@ namespace fc { namespace json_relaxed
590590
("key", key) );
591591
}
592592
in.get();
593-
auto val = json_relaxed::variant_from_stream<T, strict>( in );
593+
auto val = json_relaxed::variant_from_stream<T, strict>( in, max_depth - 1 );
594594

595595
obj(std::move(key),std::move(val));
596596
skip_white_space(in);
@@ -613,7 +613,7 @@ namespace fc { namespace json_relaxed
613613
}
614614

615615
template<typename T, bool strict>
616-
variants arrayFromStream( T& in )
616+
variants arrayFromStream( T& in, uint32_t max_depth )
617617
{
618618
variants ar;
619619
try
@@ -631,7 +631,7 @@ namespace fc { namespace json_relaxed
631631
continue;
632632
}
633633
if( skip_white_space(in) ) continue;
634-
ar.push_back( json_relaxed::variant_from_stream<T, strict>(in) );
634+
ar.push_back( json_relaxed::variant_from_stream<T, strict>(in, max_depth - 1) );
635635
skip_white_space(in);
636636
}
637637
if( in.peek() != ']' )
@@ -686,7 +686,7 @@ namespace fc { namespace json_relaxed
686686
}
687687

688688
template<typename T, bool strict>
689-
variant variant_from_stream( T& in )
689+
variant variant_from_stream( T& in, uint32_t max_depth )
690690
{
691691
skip_white_space(in);
692692
variant var;
@@ -701,11 +701,11 @@ namespace fc { namespace json_relaxed
701701
in.get();
702702
continue;
703703
case '"':
704-
return json_relaxed::stringFromStream<T, strict>( in );
704+
return json_relaxed::stringFromStream<T, strict>( in );
705705
case '{':
706-
return json_relaxed::objectFromStream<T, strict>( in );
706+
return json_relaxed::objectFromStream<T, strict>( in, max_depth - 1 );
707707
case '[':
708-
return json_relaxed::arrayFromStream<T, strict>( in );
708+
return json_relaxed::arrayFromStream<T, strict>( in, max_depth - 1 );
709709
case '-':
710710
case '+':
711711
case '.':

libraries/fc/include/fc/reflect/variant.hpp

+26-19
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,19 @@
55
namespace fc
66
{
77
template<typename T>
8-
void to_variant( const T& o, variant& v );
8+
void to_variant( const T& o, variant& v, uint32_t max_depth );
99
template<typename T>
10-
void from_variant( const variant& v, T& o );
10+
void from_variant( const variant& v, T& o, uint32_t max_depth );
1111

1212

1313
template<typename T>
1414
class to_variant_visitor
1515
{
1616
public:
17-
to_variant_visitor( mutable_variant_object& mvo, const T& v )
18-
:vo(mvo),val(v){}
17+
to_variant_visitor( mutable_variant_object& mvo, const T& v, uint32_t max_depth )
18+
:vo(mvo),val(v),_max_depth(max_depth - 1) {
19+
_FC_ASSERT( max_depth > 0, "Recursion depth exceeded!" );
20+
}
1921

2022
template<typename Member, class Class, Member (Class::*member)>
2123
void operator()( const char* name )const
@@ -28,63 +30,68 @@ namespace fc
2830
void add( mutable_variant_object& vo, const char* name, const optional<M>& v )const
2931
{
3032
if( v.valid() )
31-
vo(name,*v);
33+
vo(name, variant( *v, _max_depth ));
3234
}
3335
template<typename M>
3436
void add( mutable_variant_object& vo, const char* name, const M& v )const
35-
{ vo(name,v); }
37+
{ vo(name, variant( v, _max_depth )); }
3638

3739
mutable_variant_object& vo;
3840
const T& val;
41+
const uint32_t _max_depth;
3942
};
4043

4144
template<typename T>
4245
class from_variant_visitor : reflector_verifier_visitor<T>
4346
{
4447
public:
45-
from_variant_visitor( const variant_object& _vo, T& v )
48+
from_variant_visitor( const variant_object& _vo, T& v, uint32_t max_depth )
4649
:reflector_verifier_visitor<T>(v)
47-
,vo(_vo){}
50+
,vo(_vo)
51+
,_max_depth(max_depth - 1) {
52+
_FC_ASSERT( max_depth > 0, "Recursion depth exceeded!" );
53+
}
4854

4955
template<typename Member, class Class, Member (Class::*member)>
5056
void operator()( const char* name )const
5157
{
5258
auto itr = vo.find(name);
5359
if( itr != vo.end() )
54-
from_variant( itr->value(), this->obj.*member );
60+
from_variant( itr->value(), this->obj.*member, _max_depth );
5561
}
5662

5763
const variant_object& vo;
64+
const uint32_t _max_depth;
5865
};
5966

6067
template<typename IsReflected=fc::false_type>
6168
struct if_enum
6269
{
6370
template<typename T>
64-
static inline void to_variant( const T& v, fc::variant& vo )
71+
static inline void to_variant( const T& v, fc::variant& vo, uint32_t max_depth )
6572
{
6673
mutable_variant_object mvo;
67-
fc::reflector<T>::visit( to_variant_visitor<T>( mvo, v ) );
74+
fc::reflector<T>::visit( to_variant_visitor<T>( mvo, v, max_depth ) );
6875
vo = fc::move(mvo);
6976
}
7077
template<typename T>
71-
static inline void from_variant( const fc::variant& v, T& o )
78+
static inline void from_variant( const fc::variant& v, T& o, uint32_t max_depth )
7279
{
7380
const variant_object& vo = v.get_object();
74-
fc::reflector<T>::visit( from_variant_visitor<T>( vo, o ) );
81+
fc::reflector<T>::visit( from_variant_visitor<T>( vo, o, max_depth ) );
7582
}
7683
};
7784

7885
template<>
7986
struct if_enum<fc::true_type>
8087
{
8188
template<typename T>
82-
static inline void to_variant( const T& o, fc::variant& v )
89+
static inline void to_variant( const T& o, fc::variant& v, uint32_t max_depth = 1 )
8390
{
8491
v = fc::reflector<T>::to_fc_string(o);
8592
}
8693
template<typename T>
87-
static inline void from_variant( const fc::variant& v, T& o )
94+
static inline void from_variant( const fc::variant& v, T& o, uint32_t max_depth = 1 )
8895
{
8996
if( v.is_string() )
9097
o = fc::reflector<T>::from_string( v.get_string().c_str() );
@@ -95,15 +102,15 @@ namespace fc
95102

96103

97104
template<typename T>
98-
void to_variant( const T& o, variant& v )
105+
void to_variant( const T& o, variant& v, uint32_t max_depth )
99106
{
100-
if_enum<typename fc::reflector<T>::is_enum>::to_variant( o, v );
107+
if_enum<typename fc::reflector<T>::is_enum>::to_variant( o, v, max_depth );
101108
}
102109

103110
template<typename T>
104-
void from_variant( const variant& v, T& o )
111+
void from_variant( const variant& v, T& o, uint32_t max_depth )
105112
{
106-
if_enum<typename fc::reflector<T>::is_enum>::from_variant( v, o );
113+
if_enum<typename fc::reflector<T>::is_enum>::from_variant( v, o, max_depth );
107114
}
108115

109116
}

0 commit comments

Comments
 (0)