Skip to content

Commit

Permalink
Fix buffer overflow on multiline restricted with unterminated quote a…
Browse files Browse the repository at this point in the history
…nd multiple empty lines
  • Loading branch information
red0124 committed Mar 1, 2024
1 parent 27bd60b commit 2b6c4c5
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 31 deletions.
1 change: 1 addition & 0 deletions include/ss/converter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ class converter {

void handle_error_multiline_limit_reached() {
constexpr static auto error_msg = "multiline limit reached";
splitter_.unterminated_quote_ = false;

if constexpr (string_error) {
error_.clear();
Expand Down
35 changes: 20 additions & 15 deletions include/ss/parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -789,7 +789,8 @@ class parser {
}

if (!append_next_line_to_buffer(next_line_buffer_,
next_line_size_)) {
next_line_size_,
next_line_buffer_size_)) {
next_line_converter_.handle_error_unterminated_escape();
return;
}
Expand All @@ -807,7 +808,8 @@ class parser {
}

if (!append_next_line_to_buffer(next_line_buffer_,
next_line_size_)) {
next_line_size_,
next_line_buffer_size_)) {
next_line_converter_.handle_error_unterminated_quote();
return;
}
Expand All @@ -818,8 +820,9 @@ class parser {
return;
}

if (!append_next_line_to_buffer(next_line_buffer_,
next_line_size_)) {
if (!append_next_line_to_buffer(
next_line_buffer_, next_line_size_,
next_line_buffer_size_)) {
next_line_converter_
.handle_error_unterminated_escape();
return;
Expand Down Expand Up @@ -863,13 +866,14 @@ class parser {
return next_line_converter_.unterminated_quote();
}

void undo_remove_eol(char* buffer, size_t& string_end) {
if (crlf_) {
std::copy_n("\r\n", 2, buffer + string_end);
string_end += 2;
} else {
std::copy_n("\n", 1, buffer + string_end);
string_end += 1;
void undo_remove_eol(char* buffer, size_t& line_size,
size_t buffer_size) {
if (crlf_ && buffer_size >= line_size + 2) {
std::copy_n("\r\n", 2, buffer + line_size);
line_size += 2;
} else if (buffer_size > line_size) {
std::copy_n("\n", 1, buffer + line_size);
line_size += 1;
}
}

Expand Down Expand Up @@ -903,8 +907,9 @@ class parser {
first_size += second_size;
}

bool append_next_line_to_buffer(char*& buffer, size_t& size) {
undo_remove_eol(buffer, size);
bool append_next_line_to_buffer(char*& buffer, size_t& line_size,
size_t buffer_size) {
undo_remove_eol(buffer, line_size, buffer_size);

chars_read_ = curr_char_;
auto [next_ssize, eof] =
Expand All @@ -917,8 +922,8 @@ class parser {

++line_number_;
size_t next_size = remove_eol(helper_buffer_, next_ssize);
realloc_concat(buffer, size, next_line_buffer_size_, helper_buffer_,
next_size);
realloc_concat(buffer, line_size, next_line_buffer_size_,
helper_buffer_, next_size);
return true;
}

Expand Down
36 changes: 21 additions & 15 deletions ssp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2021,6 +2021,7 @@ class converter {

void handle_error_multiline_limit_reached() {
constexpr static auto error_msg = "multiline limit reached";
splitter_.unterminated_quote_ = false;

if constexpr (string_error) {
error_.clear();
Expand Down Expand Up @@ -3024,7 +3025,8 @@ class parser {
}

if (!append_next_line_to_buffer(next_line_buffer_,
next_line_size_)) {
next_line_size_,
next_line_buffer_size_)) {
next_line_converter_.handle_error_unterminated_escape();
return;
}
Expand All @@ -3042,7 +3044,8 @@ class parser {
}

if (!append_next_line_to_buffer(next_line_buffer_,
next_line_size_)) {
next_line_size_,
next_line_buffer_size_)) {
next_line_converter_.handle_error_unterminated_quote();
return;
}
Expand All @@ -3053,8 +3056,9 @@ class parser {
return;
}

if (!append_next_line_to_buffer(next_line_buffer_,
next_line_size_)) {
if (!append_next_line_to_buffer(
next_line_buffer_, next_line_size_,
next_line_buffer_size_)) {
next_line_converter_
.handle_error_unterminated_escape();
return;
Expand Down Expand Up @@ -3098,13 +3102,14 @@ class parser {
return next_line_converter_.unterminated_quote();
}

void undo_remove_eol(char* buffer, size_t& string_end) {
if (crlf_) {
std::copy_n("\r\n", 2, buffer + string_end);
string_end += 2;
} else {
std::copy_n("\n", 1, buffer + string_end);
string_end += 1;
void undo_remove_eol(char* buffer, size_t& line_size,
size_t buffer_size) {
if (crlf_ && buffer_size >= line_size + 2) {
std::copy_n("\r\n", 2, buffer + line_size);
line_size += 2;
} else if (buffer_size > line_size) {
std::copy_n("\n", 1, buffer + line_size);
line_size += 1;
}
}

Expand Down Expand Up @@ -3138,8 +3143,9 @@ class parser {
first_size += second_size;
}

bool append_next_line_to_buffer(char*& buffer, size_t& size) {
undo_remove_eol(buffer, size);
bool append_next_line_to_buffer(char*& buffer, size_t& line_size,
size_t buffer_size) {
undo_remove_eol(buffer, line_size, buffer_size);

chars_read_ = curr_char_;
auto [next_ssize, eof] =
Expand All @@ -3152,8 +3158,8 @@ class parser {

++line_number_;
size_t next_size = remove_eol(helper_buffer_, next_ssize);
realloc_concat(buffer, size, next_line_buffer_size_, helper_buffer_,
next_size);
realloc_concat(buffer, line_size, next_line_buffer_size_,
helper_buffer_, next_size);
return true;
}

Expand Down
3 changes: 2 additions & 1 deletion test/test_parser1_3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@ TEST_CASE_TEMPLATE("test multiline restricted", T, ParserOptionCombinations) {
out << "5,6,just\\\n\\\nstrings" << std::endl;
#endif
out << "7,8,ju\\\n\\\n\\\nnk" << std::endl;
out << "99,100,\"\n\n\n\n" << std::endl;
out << "9,10,\"just\\\n\nstrings\"" << std::endl;
out << "11,12,\"ju\\\n|\n\n\n\n\nk\"" << std::endl;
out << "13,14,\"ju\\\n\\\n15,16\"\\\n\\\\\n\nnk\"" << std::endl;
out << "17,18,\"ju\\\n\\\n\\\n\\\\\n\nnk\"" << std::endl;
out << "19,20,just strings" << std::endl;
}
auto bad_lines = 15;
auto bad_lines = 20;
auto num_errors = 0;

auto [p, _] =
Expand Down

0 comments on commit 2b6c4c5

Please sign in to comment.