Skip to content

Commit

Permalink
Added max_nesting_depth to csv_options
Browse files Browse the repository at this point in the history
  • Loading branch information
danielaparker committed Jan 26, 2025
1 parent 4179f2b commit ae3c018
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 1 deletion.
2 changes: 2 additions & 0 deletions doc/ref/csv/basic_csv_options.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ Specifies options for reading and writing CSV data.

Option|Reading|Writing
------|-------|----------
flat (since 1.2.0)| |Indicates whether the encoder should process JSON as "flat" (without navigating through nested structures).
max_nesting_depth (since 1.2.0)|&npsp;|Maximum nesting depth allowed in the input when encoding nested JSON to CSV
nan_to_str|Substitute string with `NaN`, if enabled|Sets a string replacement for `NaN` when writing JSON
inf_to_str|Substitute string with `infinity`, if enabled|Sets a string replacement for infinity when writing JSON
neginf_to_str|Substitute string with `negative infinity`, if enabled|Sets a string replacement for negative infinity when writing JSON
Expand Down
12 changes: 12 additions & 0 deletions include/jsoncons_ext/csv/csv_encoder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ class basic_csv_encoder final : public basic_json_visitor<CharT>

Sink sink_;
bool flat_;
std::size_t max_nesting_depth_;
bool has_column_mapping_;
bool has_column_names_;
char_type field_delimiter_;
Expand Down Expand Up @@ -156,6 +157,7 @@ class basic_csv_encoder final : public basic_json_visitor<CharT>
const Allocator& alloc = Allocator())
: sink_(std::forward<Sink>(sink)),
flat_(options.flat()),
max_nesting_depth_(options.max_nesting_depth()),
has_column_mapping_(!options.column_mapping().empty()),
has_column_names_(!options.column_names().empty()),
field_delimiter_(options.field_delimiter()),
Expand Down Expand Up @@ -279,6 +281,11 @@ class basic_csv_encoder final : public basic_json_visitor<CharT>
}
return true;
}
if (JSONCONS_UNLIKELY(stack_.size() >= max_nesting_depth_))
{
ec = csv_errc::max_nesting_depth_exceeded;
return false;
}

// legacy
if (has_column_names_ && stack_.back().count_ == 0)
Expand Down Expand Up @@ -498,6 +505,11 @@ class basic_csv_encoder final : public basic_json_visitor<CharT>
}
return true;
}
if (JSONCONS_UNLIKELY(stack_.size() >= max_nesting_depth_))
{
ec = csv_errc::max_nesting_depth_exceeded;
return false;
}
// legacy
if (has_column_names_ && stack_.back().count_ == 0)
{
Expand Down
5 changes: 4 additions & 1 deletion include/jsoncons_ext/csv/csv_error.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ namespace jsoncons { namespace csv {
syntax_error,
invalid_parse_state,
invalid_escaped_char,
unexpected_char_between_fields
unexpected_char_between_fields,
max_nesting_depth_exceeded
};

class csv_error_category_impl
Expand Down Expand Up @@ -51,6 +52,8 @@ class csv_error_category_impl
return "Invalid character following quote escape character";
case csv_errc::unexpected_char_between_fields:
return "Unexpected character between fields";
case csv_errc::max_nesting_depth_exceeded:
return "Data item nesting exceeds limit in options";
default:
return "Unknown CSV parser error";
}
Expand Down
13 changes: 13 additions & 0 deletions include/jsoncons_ext/csv/csv_options.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ class basic_csv_options_common
string_type neginf_to_str_;
string_type column_names_;
std::vector<std::pair<std::string,std::string>> column_mapping_;
std::size_t max_nesting_depth_{1024};

protected:
basic_csv_options_common()
Expand Down Expand Up @@ -322,6 +323,11 @@ class basic_csv_options_common
return flat_;
}

std::size_t max_nesting_depth() const
{
return max_nesting_depth_;
}

char_type field_delimiter() const
{
return field_delimiter_;
Expand Down Expand Up @@ -687,6 +693,7 @@ class basic_csv_options final : public basic_csv_decode_options<CharT>, public b
using basic_csv_decode_options<CharT>::inf_to_num;
using basic_csv_decode_options<CharT>::neginf_to_num;
using basic_csv_decode_options<CharT>::flat;
using basic_csv_decode_options<CharT>::max_nesting_depth;
using basic_csv_decode_options<CharT>::field_delimiter;
using basic_csv_decode_options<CharT>::subfield_delimiter;
using basic_csv_decode_options<CharT>::quote_char;
Expand Down Expand Up @@ -836,6 +843,12 @@ class basic_csv_options final : public basic_csv_decode_options<CharT>, public b
return *this;
}

basic_csv_options& max_nesting_depth(std::size_t value)
{
this->max_nesting_depth_ = value;
return *this;
}

basic_csv_options& field_delimiter(char_type value)
{
this->field_delimiter_ = value;
Expand Down

0 comments on commit ae3c018

Please sign in to comment.