mirror of
https://github.com/ToruNiina/toml11.git
synced 2024-09-19 15:19:54 +00:00
fix: limit value recursion in array/inl-table
to avoid parse_value/parse_array recursion
This commit is contained in:
parent
01a0e93e5f
commit
8e214ec411
@ -53,7 +53,7 @@ literal_internal_impl(::toml::detail::location loc)
|
|||||||
// If it is neither a table-key or a array-of-table-key, it may be a value.
|
// If it is neither a table-key or a array-of-table-key, it may be a value.
|
||||||
if(!is_table_key && !is_aots_key)
|
if(!is_table_key && !is_aots_key)
|
||||||
{
|
{
|
||||||
if(auto data = ::toml::detail::parse_value<value_type>(loc))
|
if(auto data = ::toml::detail::parse_value<value_type>(loc, 0))
|
||||||
{
|
{
|
||||||
return data.unwrap();
|
return data.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "combinator.hpp"
|
#include "combinator.hpp"
|
||||||
#include "lexer.hpp"
|
#include "lexer.hpp"
|
||||||
|
#include "macros.hpp"
|
||||||
#include "region.hpp"
|
#include "region.hpp"
|
||||||
#include "result.hpp"
|
#include "result.hpp"
|
||||||
#include "types.hpp"
|
#include "types.hpp"
|
||||||
@ -22,6 +23,8 @@
|
|||||||
#endif // __cpp_lib_filesystem
|
#endif // __cpp_lib_filesystem
|
||||||
#endif // TOML11_DISABLE_STD_FILESYSTEM
|
#endif // TOML11_DISABLE_STD_FILESYSTEM
|
||||||
|
|
||||||
|
#define TOML11_VALUE_RECURSION_LIMIT 64
|
||||||
|
|
||||||
namespace toml
|
namespace toml
|
||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
@ -1138,15 +1141,23 @@ parse_key(location& loc)
|
|||||||
|
|
||||||
// forward-decl to implement parse_array and parse_table
|
// forward-decl to implement parse_array and parse_table
|
||||||
template<typename Value>
|
template<typename Value>
|
||||||
result<Value, std::string> parse_value(location&);
|
result<Value, std::string> parse_value(location&, const std::size_t n_rec);
|
||||||
|
|
||||||
template<typename Value>
|
template<typename Value>
|
||||||
result<std::pair<typename Value::array_type, region>, std::string>
|
result<std::pair<typename Value::array_type, region>, std::string>
|
||||||
parse_array(location& loc)
|
parse_array(location& loc, const std::size_t n_rec)
|
||||||
{
|
{
|
||||||
using value_type = Value;
|
using value_type = Value;
|
||||||
using array_type = typename value_type::array_type;
|
using array_type = typename value_type::array_type;
|
||||||
|
|
||||||
|
if(n_rec > TOML11_VALUE_RECURSION_LIMIT)
|
||||||
|
{
|
||||||
|
// parse_array does not have any way to handle recursive error currently...
|
||||||
|
throw syntax_error(std::string("toml::parse_array: recursion limit ("
|
||||||
|
TOML11_STRINGIZE(TOML11_VALUE_RECURSION_LIMIT) ") exceeded"),
|
||||||
|
source_location(loc));
|
||||||
|
}
|
||||||
|
|
||||||
const auto first = loc.iter();
|
const auto first = loc.iter();
|
||||||
if(loc.iter() == loc.end())
|
if(loc.iter() == loc.end())
|
||||||
{
|
{
|
||||||
@ -1173,7 +1184,7 @@ parse_array(location& loc)
|
|||||||
region(loc, first, loc.iter())));
|
region(loc, first, loc.iter())));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(auto val = parse_value<value_type>(loc))
|
if(auto val = parse_value<value_type>(loc, n_rec+1))
|
||||||
{
|
{
|
||||||
// After TOML v1.0.0-rc.1, array becomes to be able to have values
|
// After TOML v1.0.0-rc.1, array becomes to be able to have values
|
||||||
// with different types. So here we will omit this by default.
|
// with different types. So here we will omit this by default.
|
||||||
@ -1247,7 +1258,7 @@ parse_array(location& loc)
|
|||||||
|
|
||||||
template<typename Value>
|
template<typename Value>
|
||||||
result<std::pair<std::pair<std::vector<key>, region>, Value>, std::string>
|
result<std::pair<std::pair<std::vector<key>, region>, Value>, std::string>
|
||||||
parse_key_value_pair(location& loc)
|
parse_key_value_pair(location& loc, const std::size_t n_rec)
|
||||||
{
|
{
|
||||||
using value_type = Value;
|
using value_type = Value;
|
||||||
|
|
||||||
@ -1294,7 +1305,7 @@ parse_key_value_pair(location& loc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const auto after_kvsp = loc.iter(); // err msg
|
const auto after_kvsp = loc.iter(); // err msg
|
||||||
auto val = parse_value<value_type>(loc);
|
auto val = parse_value<value_type>(loc, n_rec);
|
||||||
if(!val)
|
if(!val)
|
||||||
{
|
{
|
||||||
std::string msg;
|
std::string msg;
|
||||||
@ -1341,7 +1352,7 @@ result<std::pair<std::vector<key>, region>, std::string>
|
|||||||
parse_array_table_key(location& loc);
|
parse_array_table_key(location& loc);
|
||||||
template<typename Value>
|
template<typename Value>
|
||||||
result<std::pair<typename Value::table_type, region>, std::string>
|
result<std::pair<typename Value::table_type, region>, std::string>
|
||||||
parse_inline_table(location& loc);
|
parse_inline_table(location& loc, const std::size_t n_rec);
|
||||||
|
|
||||||
// The following toml file is allowed.
|
// The following toml file is allowed.
|
||||||
// ```toml
|
// ```toml
|
||||||
@ -1379,7 +1390,7 @@ bool is_valid_forward_table_definition(const Value& fwd, const Value& inserting,
|
|||||||
inserting_reg = ptr->str();
|
inserting_reg = ptr->str();
|
||||||
}
|
}
|
||||||
location inserting_def("internal", std::move(inserting_reg));
|
location inserting_def("internal", std::move(inserting_reg));
|
||||||
if(const auto inlinetable = parse_inline_table<Value>(inserting_def))
|
if(const auto inlinetable = parse_inline_table<Value>(inserting_def, 0))
|
||||||
{
|
{
|
||||||
// check if we are overwriting existing table.
|
// check if we are overwriting existing table.
|
||||||
// ```toml
|
// ```toml
|
||||||
@ -1810,11 +1821,18 @@ insert_nested_key(typename Value::table_type& root, const Value& v,
|
|||||||
|
|
||||||
template<typename Value>
|
template<typename Value>
|
||||||
result<std::pair<typename Value::table_type, region>, std::string>
|
result<std::pair<typename Value::table_type, region>, std::string>
|
||||||
parse_inline_table(location& loc)
|
parse_inline_table(location& loc, const std::size_t n_rec)
|
||||||
{
|
{
|
||||||
using value_type = Value;
|
using value_type = Value;
|
||||||
using table_type = typename value_type::table_type;
|
using table_type = typename value_type::table_type;
|
||||||
|
|
||||||
|
if(n_rec > TOML11_VALUE_RECURSION_LIMIT)
|
||||||
|
{
|
||||||
|
throw syntax_error(std::string("toml::parse_inline_table: recursion limit ("
|
||||||
|
TOML11_STRINGIZE(TOML11_VALUE_RECURSION_LIMIT) ") exceeded"),
|
||||||
|
source_location(loc));
|
||||||
|
}
|
||||||
|
|
||||||
const auto first = loc.iter();
|
const auto first = loc.iter();
|
||||||
table_type retval;
|
table_type retval;
|
||||||
if(!(loc.iter() != loc.end() && *loc.iter() == '{'))
|
if(!(loc.iter() != loc.end() && *loc.iter() == '{'))
|
||||||
@ -1835,7 +1853,7 @@ parse_inline_table(location& loc)
|
|||||||
// it starts from "{". it should be formatted as inline-table
|
// it starts from "{". it should be formatted as inline-table
|
||||||
while(loc.iter() != loc.end())
|
while(loc.iter() != loc.end())
|
||||||
{
|
{
|
||||||
const auto kv_r = parse_key_value_pair<value_type>(loc);
|
const auto kv_r = parse_key_value_pair<value_type>(loc, n_rec+1);
|
||||||
if(!kv_r)
|
if(!kv_r)
|
||||||
{
|
{
|
||||||
return err(kv_r.unwrap_err());
|
return err(kv_r.unwrap_err());
|
||||||
@ -2079,7 +2097,7 @@ parse_value_helper(result<std::pair<T, region>, std::string> rslt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename Value>
|
template<typename Value>
|
||||||
result<Value, std::string> parse_value(location& loc)
|
result<Value, std::string> parse_value(location& loc, const std::size_t n_rec)
|
||||||
{
|
{
|
||||||
const auto first = loc.iter();
|
const auto first = loc.iter();
|
||||||
if(first == loc.end())
|
if(first == loc.end())
|
||||||
@ -2104,8 +2122,8 @@ result<Value, std::string> parse_value(location& loc)
|
|||||||
case value_t::local_datetime : {return parse_value_helper<Value>(parse_local_datetime(loc) );}
|
case value_t::local_datetime : {return parse_value_helper<Value>(parse_local_datetime(loc) );}
|
||||||
case value_t::local_date : {return parse_value_helper<Value>(parse_local_date(loc) );}
|
case value_t::local_date : {return parse_value_helper<Value>(parse_local_date(loc) );}
|
||||||
case value_t::local_time : {return parse_value_helper<Value>(parse_local_time(loc) );}
|
case value_t::local_time : {return parse_value_helper<Value>(parse_local_time(loc) );}
|
||||||
case value_t::array : {return parse_value_helper<Value>(parse_array<Value>(loc) );}
|
case value_t::array : {return parse_value_helper<Value>(parse_array<Value>(loc, n_rec));}
|
||||||
case value_t::table : {return parse_value_helper<Value>(parse_inline_table<Value>(loc));}
|
case value_t::table : {return parse_value_helper<Value>(parse_inline_table<Value>(loc, n_rec));}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
const auto msg = format_underline("toml::parse_value: "
|
const auto msg = format_underline("toml::parse_value: "
|
||||||
@ -2270,7 +2288,7 @@ parse_ml_table(location& loc)
|
|||||||
return ok(tab);
|
return ok(tab);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(const auto kv = parse_key_value_pair<value_type>(loc))
|
if(const auto kv = parse_key_value_pair<value_type>(loc, 0))
|
||||||
{
|
{
|
||||||
const auto& kvpair = kv.unwrap();
|
const auto& kvpair = kv.unwrap();
|
||||||
const std::vector<key>& keys = kvpair.first.first;
|
const std::vector<key>& keys = kvpair.first.first;
|
||||||
|
Loading…
Reference in New Issue
Block a user