From 04b5aace73461a5090720e3cda0ad5424cd5d640 Mon Sep 17 00:00:00 2001 From: eidheim Date: Sun, 20 Sep 2020 13:02:32 +0200 Subject: [PATCH] Fixes #440: segmentation fault when running regex on very long lines. Also minor cleanup of Terminall::find_link, and added extra Termina::find_link tests. --- src/terminal.cpp | 11 +++--- src/terminal.hpp | 2 +- tests/terminal_test.cpp | 79 ++++++++++++++++++++++++++++++++++++----- 3 files changed, 77 insertions(+), 15 deletions(-) diff --git a/src/terminal.cpp b/src/terminal.cpp index e4b65e1..e278878 100644 --- a/src/terminal.cpp +++ b/src/terminal.cpp @@ -373,7 +373,10 @@ bool Terminal::on_motion_notify_event(GdkEventMotion *event) { return Gtk::TextView::on_motion_notify_event(event); } -boost::optional Terminal::find_link(const std::string &line, size_t pos, size_t length) { +boost::optional Terminal::find_link(const std::string &line) { + if(line.size() >= 1000) // Due to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86164 + return {}; + const static std::regex link_regex("^([A-Z]:)?([^:]+):([0-9]+):([0-9]+): .*$|" // C/C++ compile warning/error/rename usages "^In file included from ([A-Z]:)?([^:]+):([0-9]+)[:,]$|" // C/C++ extra compile warning/error info "^ from ([A-Z]:)?([^:]+):([0-9]+)[:,]$|" // C/C++ extra compile warning/error info (gcc) @@ -385,12 +388,10 @@ boost::optional Terminal::find_link(const std::string &line, siz "^ +at .*?\\(([A-Z]:)?([^:]+):([0-9]+):([0-9]+)\\).*$|" // Node.js stack trace "^ +at ([A-Z]:)?([^:]+):([0-9]+):([0-9]+).*$|" // Node.js stack trace "^ File \"([A-Z]:)?([^\"]+)\", line ([0-9]+), in .*$|" // Python - "^.*?([A-Z]:)?([a-zA-Z0-9._\\\\/][a-zA-Z0-9._\\-\\\\/]*):([0-9]+):([0-9]+).*$", // Posix file:line:column + "^.*?([A-Z]:)?([a-zA-Z0-9._\\\\/][a-zA-Z0-9._\\-\\\\/]*):([0-9]+):([0-9]+).*$", // Posix path:line:column std::regex::optimize); std::smatch sm; - if(std::regex_match(line.cbegin() + pos, - line.cbegin() + (length == std::string::npos ? line.size() : std::min(pos + length, line.size())), - sm, link_regex)) { + if(std::regex_match(line, sm, link_regex)) { for(size_t sub = 1; sub < link_regex.mark_count();) { size_t subs = (sub == 1 || sub == 1 + 4 + 3 + 3 || diff --git a/src/terminal.hpp b/src/terminal.hpp index 0269fb9..a89673b 100644 --- a/src/terminal.hpp +++ b/src/terminal.hpp @@ -57,7 +57,7 @@ private: std::string path; int line, line_index; }; - boost::optional find_link(const std::string &line, size_t pos = 0, size_t length = std::string::npos); + static boost::optional find_link(const std::string &line); Mutex processes_mutex; std::vector> processes GUARDED_BY(processes_mutex); diff --git a/tests/terminal_test.cpp b/tests/terminal_test.cpp index 3fbb686..72e829a 100644 --- a/tests/terminal_test.cpp +++ b/tests/terminal_test.cpp @@ -26,7 +26,7 @@ int main() { // Testing links { - auto link = terminal.find_link("~/test/test.cc:7:41: error: expected ';' after expression."); + auto link = Terminal::find_link("~/test/test.cc:7:41: error: expected ';' after expression."); assert(link); assert(link->start_pos == 0); assert(link->end_pos == 19); @@ -35,7 +35,34 @@ int main() { assert(link->line_index == 41); } { - auto link = terminal.find_link("Assertion failed: (false), function main, file ~/test/test.cc, line 15."); + auto link = Terminal::find_link("In file included from ./test/test.cc:2,"); + assert(link); + assert(link->start_pos == 22); + assert(link->end_pos == 38); + assert(link->path == "./test/test.cc"); + assert(link->line == 2); + assert(link->line_index == 1); + } + { + auto link = Terminal::find_link(" from ./test/test.cc:2:"); + assert(link); + assert(link->start_pos == 22); + assert(link->end_pos == 38); + assert(link->path == "./test/test.cc"); + assert(link->line == 2); + assert(link->line_index == 1); + } + { + auto link = Terminal::find_link(" --> src/main.rs:16:4"); + assert(link); + assert(link->start_pos == 6); + assert(link->end_pos == 22); + assert(link->path == "src/main.rs"); + assert(link->line == 16); + assert(link->line_index == 4); + } + { + auto link = Terminal::find_link("Assertion failed: (false), function main, file ~/test/test.cc, line 15."); assert(link); assert(link->start_pos == 47); assert(link->end_pos == 70); @@ -44,7 +71,7 @@ int main() { assert(link->line_index == 1); } { - auto link = terminal.find_link("test: ~/examples/main.cpp:17: int main(int, char**): Assertion `false' failed."); + auto link = Terminal::find_link("test: ~/examples/main.cpp:17: int main(int, char**): Assertion `false' failed."); assert(link); assert(link->start_pos == 6); assert(link->end_pos == 28); @@ -53,7 +80,7 @@ int main() { assert(link->line_index == 1); } { - auto link = terminal.find_link("ERROR:~/test/test.cc:36:int main(): assertion failed: (false)"); + auto link = Terminal::find_link("ERROR:~/test/test.cc:36:int main(): assertion failed: (false)"); assert(link); assert(link->start_pos == 6); assert(link->end_pos == 23); @@ -62,16 +89,34 @@ int main() { assert(link->line_index == 1); } { - auto link = terminal.find_link(" --> src/main.rs:16:4"); + auto link = Terminal::find_link("/test/test.js:10"); assert(link); - assert(link->start_pos == 6); - assert(link->end_pos == 22); - assert(link->path == "src/main.rs"); + assert(link->start_pos == 0); + assert(link->end_pos == 16); + assert(link->path == "/test/test.js"); + assert(link->line == 10); + assert(link->line_index == 1); + } + { + auto link = Terminal::find_link(" at something (src/main.js:16:4)"); + assert(link); + assert(link->start_pos == 16); + assert(link->end_pos == 32); + assert(link->path == "src/main.js"); + assert(link->line == 16); + assert(link->line_index == 4); + } + { + auto link = Terminal::find_link(" at src/main.js:16:4"); + assert(link); + assert(link->start_pos == 5); + assert(link->end_pos == 21); + assert(link->path == "src/main.js"); assert(link->line == 16); assert(link->line_index == 4); } { - auto link = terminal.find_link(R"( File "/home/test/test.py", line 4, in )"); + auto link = Terminal::find_link(R"( File "/home/test/test.py", line 4, in )"); assert(link); assert(link->start_pos == 8); assert(link->end_pos == 35); @@ -79,6 +124,22 @@ int main() { assert(link->line == 4); assert(link->line_index == 1); } + { + auto link = Terminal::find_link("Testing ./posix_path/test.txt:10:20 here"); + assert(link); + assert(link->start_pos == 8); + assert(link->end_pos == 35); + assert(link->path == "./posix_path/test.txt"); + assert(link->line == 10); + assert(link->line_index == 20); + } + { + // Avoid https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86164 + std::string long_line; + for(size_t i = 0; i < 50000; ++i) + long_line += "x"; + assert(!Terminal::find_link("/home/test/test.txt:1:1: " + long_line)); + } // Testing print {