@@ -820,6 +820,9 @@ namespace crow
820
820
821
821
inline rvalue load_nocopy_internal (char * data, size_t size)
822
822
{
823
+ // Defend against excessive recursion
824
+ static constexpr unsigned max_depth = 10000 ;
825
+
823
826
// static const char* escaped = "\"\\/\b\f\n\r\t";
824
827
struct Parser
825
828
{
@@ -902,10 +905,10 @@ namespace crow
902
905
return {};
903
906
}
904
907
905
- rvalue decode_list ()
908
+ rvalue decode_list (unsigned depth )
906
909
{
907
910
rvalue ret (type::List);
908
- if (crow_json_unlikely (!consume (' [' )))
911
+ if (crow_json_unlikely (!consume (' [' )) || crow_json_unlikely (depth > max_depth) )
909
912
{
910
913
ret.set_error ();
911
914
return ret;
@@ -919,7 +922,7 @@ namespace crow
919
922
920
923
while (1 )
921
924
{
922
- auto v = decode_value ();
925
+ auto v = decode_value (depth + 1 );
923
926
if (crow_json_unlikely (!v))
924
927
{
925
928
ret.set_error ();
@@ -1068,14 +1071,15 @@ namespace crow
1068
1071
return {};
1069
1072
}
1070
1073
1071
- rvalue decode_value ()
1074
+
1075
+ rvalue decode_value (unsigned depth)
1072
1076
{
1073
1077
switch (*data)
1074
1078
{
1075
1079
case ' [' :
1076
- return decode_list ();
1080
+ return decode_list (depth + 1 );
1077
1081
case ' {' :
1078
- return decode_object ();
1082
+ return decode_object (depth + 1 );
1079
1083
case ' "' :
1080
1084
return decode_string ();
1081
1085
case ' t' :
@@ -1122,10 +1126,10 @@ namespace crow
1122
1126
return {};
1123
1127
}
1124
1128
1125
- rvalue decode_object ()
1129
+ rvalue decode_object (unsigned depth )
1126
1130
{
1127
1131
rvalue ret (type::Object);
1128
- if (crow_json_unlikely (!consume (' {' )))
1132
+ if (crow_json_unlikely (!consume (' {' )) || crow_json_unlikely (depth > max_depth) )
1129
1133
{
1130
1134
ret.set_error ();
1131
1135
return ret;
@@ -1160,7 +1164,7 @@ namespace crow
1160
1164
auto key = t.s ();
1161
1165
1162
1166
ws_skip ();
1163
- auto v = decode_value ();
1167
+ auto v = decode_value (depth + 1 );
1164
1168
if (crow_json_unlikely (!v))
1165
1169
{
1166
1170
ret.set_error ();
@@ -1188,7 +1192,7 @@ namespace crow
1188
1192
rvalue parse ()
1189
1193
{
1190
1194
ws_skip ();
1191
- auto ret = decode_value (); // or decode object?
1195
+ auto ret = decode_value (0 ); // or decode object?
1192
1196
ws_skip ();
1193
1197
if (ret && *data != ' \0 ' )
1194
1198
ret.set_error ();
0 commit comments