Created attachment 1194363 [details] abrt info -d Description of problem: Evolution crashes when replying to a certain mail Version-Release number of selected component (if applicable): Evolution 3.20.5 How reproducible: always Steps to Reproduce: 1. Open evolution 2. Reply to the mail (received over IMAP) Actual results: Evolution crashes Expected results: Evolution opens a reply editor Additional info: Crash info as provided by ABRT info is attached. If you need the email source, please let me know.
Created attachment 1194364 [details] core-backtrace
Thanks for a bug report. It seems to me that your email triggered some busy-loop issue in the /usr/lib64/libpcre.so.1.2.7. It would be helpful to have the corresponding message for testing. Make sure you'll not expose anything private. Thanks in advance.
Is there a way to flag this bug report as confidential / restrict access?
Sure, I did so (I think). You should be still able to still see the bug report, and the updates on it, because you are the reporter. In any case, if you are unsure and do not want to send the message in the wild, then feel free to send it attached only to my bugzilla email address, just name this bug report in the subject, thus I'd not overlook it in my spam folder. This way it's safer than relying of a flag which someone can uncheck accidentally.
Thanks, I have sent the questionable email as an attachment to your email address.
Created attachment 1196477 [details] Anonymized test message Thanks for the test message. I anonymized it and I'm also able to reproduce it when I reply or edit as new it into the Plain Text mode and choose to Lose Formatting. It seems to me that the regexp which looks for links, email addresses and such triggers some recursion, because the crash is basically about stack overflow. I can reproduce it with your message both in the 3.20.5 and in the current development version, which uses WebKit2 (the message causes crash of the WebProcess, not the UI). The "full" backtrace looks like this: Thread 1 "evolution" received signal SIGSEGV, Segmentation fault. match (eptr=0x4ea0c04 "xxxxxx xxxx-xxxxx XXX: https://xxxxxxxx.xxxx.xx:oooo/XxxxxXxxxxxx/Xxxxxxxx/Xxxxxxxxxxx oooo-oo-oo oo:oo:oo oooo [XxxxXxxxxx$o] --> XXXXXXXX https://xxxxxxxx.xxxx.xx:oooo/XxxxxXxxxxxx/Xxxxxxxx/Xxxxx"..., ecode=0x4e84d55 "\035&\035n\035b\035s\035p\035;x", mstart=0x4e9ce03 "https://xxxxxxxx.xxxx.xx:oooo/XxxxxXxxxxxx/Xxxxxxxx/Xxxxxxxxxxx oooo-oo-oo oo:oo:oo oooo [xxxoxxxxxxx.XxxxxxxxXxxxxxxx] Xxxxxxxxxxx XXX xxxxxxxx xxxxxxxxx oooo-oo-oo oo:oo:oo oooo [xxxoxxxxxxx.Xxxxxxx"..., offset_top=4, md=0x7fffffffca00, eptrb=0x0, rdepth=15876) at pcre_exec.c:516 516 { (gdb) bt #0 0x00007fffe423e0ba in match (eptr=0x4ea0c04 "xxxxxx xxxx-xxxxx XXX: https://xxxxxxxx.xxxx.xx:oooo/XxxxxXxxxxxx/Xxxxxxxx/Xxxxxxxxxxx oooo-oo-oo oo:oo:oo oooo [XxxxXxxxxx$o] --> XXXXXXXX https://xxxxxxxx.xxxx.xx:oooo/XxxxxXxxxxxx/Xxxxxxxx/Xxxxx"..., ecode=0x4e84d55 "\035&\035n\035b\035s\035p\035;x", mstart=0x4e9ce03 "https://xxxxxxxx.xxxx.xx:oooo/XxxxxXxxxxxx/Xxxxxxxx/Xxxxxxxxxxx oooo-oo-oo oo:oo:oo oooo [xxxoxxxxxxx.XxxxxxxxXxxxxxxx] Xxxxxxxxxxx XXX xxxxxxxx xxxxxxxxx oooo-oo-oo oo:oo:oo oooo [xxxoxxxxxxx.Xxxxxxx"..., offset_top=4, md=0x7fffffffca00, eptrb=0x0, rdepth=15876) at pcre_exec.c:516 #1 0x00007fffe423f086 in match (eptr=<optimized out>, ecode=0x4e84d52 "~", mstart=0x4e9ce03 "https://xxxxxxxx.xxxx.xx:oooo/XxxxxXxxxxxx/Xxxxxxxx/Xxxxxxxxxxx oooo-oo-oo oo:oo:oo oooo [xxxoxxxxxxx.XxxxxxxxXxxxxxxx] Xxxxxxxxxxx XXX xxxxxxxx xxxxxxxxx oooo-oo-oo oo:oo:oo oooo [xxxoxxxxxxx.Xxxxxxx"..., offset_top=4, md=0x7fffffffca00, eptrb=0x0, rdepth=<optimized out>) at pcre_exec.c:1612 #2 0x00007fffe424c662 in match (eptr=<optimized out>, ecode=0x4e84d65 "y", mstart=0x4e9ce03 "https://xxxxxxxx.xxxx.xx:oooo/XxxxxXxxxxxx/Xxxxxxxx/Xxxxxxxxxxx oooo-oo-oo oo:oo:oo oooo [xxxoxxxxxxx.XxxxxxxxXxxxxxxx] Xxxxxxxxxxx XXX xxxxxxxx xxxxxxxxx oooo-oo-oo oo:oo:oo oooo [xxxoxxxxxxx.Xxxxxxx"..., offset_top=4, md=0x7fffffffca00, eptrb=0x0, rdepth=<optimized out>) at pcre_exec.c:2061 #3 0x00007fffe424c662 in match (eptr=<optimized out>, ecode=0x4e84d65 "y", mstart=0x4e9ce03 "https://xxxxxxxx.xxxx.xx:oooo/XxxxxXxxxxxx/Xxxxxxxx/Xxxxxxxxxxx oooo-oo-oo oo:oo:oo oooo [xxxoxxxxxxx.XxxxxxxxXxxxxxxx] Xxxxxxxxxxx XXX xxxxxxxx xxxxxxxxx oooo-oo-oo oo:oo:oo oooo [xxxoxxxxxxx.Xxxxxxx"..., offset_top=4, md=0x7fffffffca00, eptrb=0x0, rdepth=<optimized out>) at pcre_exec.c:2061 ... #15873 0x00007fffe424c662 in match (eptr=<optimized out>, ecode=0x4e84d65 "y", mstart=0x4e9ce03 "https://xxxxxxxx.xxxx.xx:oooo/XxxxxXxxxxxx/Xxxxxxxx/Xxxxxxxxxxx oooo-oo-oo oo:oo:oo oooo [xxxoxxxxxxx.XxxxxxxxXxxxxxxx] Xxxxxxxxxxx XXX xxxxxxxx xxxxxxxxx oooo-oo-oo oo:oo:oo oooo [xxxoxxxxxxx.Xxxxxxx"..., offset_top=4, md=0x7fffffffca00, eptrb=0x0, rdepth=<optimized out>) at pcre_exec.c:2061 #15874 0x00007fffe424c662 in match (eptr=<optimized out>, ecode=0x4e84d65 "y", mstart=0x4e9ce03 "https://xxxxxxxx.xxxx.xx:oooo/XxxxxXxxxxxx/Xxxxxxxx/Xxxxxxxxxxx oooo-oo-oo oo:oo:oo oooo [xxxoxxxxxxx.XxxxxxxxXxxxxxxx] Xxxxxxxxxxx XXX xxxxxxxx xxxxxxxxx oooo-oo-oo oo:oo:oo oooo [xxxoxxxxxxx.Xxxxxxx"..., offset_top=4, md=0x7fffffffca00, eptrb=0x0, rdepth=<optimized out>) at pcre_exec.c:2061 #15875 0x00007fffe423fce6 in match (eptr=<optimized out>, ecode=0x4e84d4e "\222\203", mstart=0x4e9ce03 "https://xxxxxxxx.xxxx.xx:oooo/XxxxxXxxxxxx/Xxxxxxxx/Xxxxxxxxxxx oooo-oo-oo oo:oo:oo oooo [xxxoxxxxxxx.XxxxxxxxXxxxxxxx] Xxxxxxxxxxx XXX xxxxxxxx xxxxxxxxx oooo-oo-oo oo:oo:oo oooo [xxxoxxxxxxx.Xxxxxxx"..., offset_top=4, md=0x7fffffffca00, eptrb=0x0, rdepth=<optimized out>) at pcre_exec.c:1878 #15876 0x00007fffe42408e3 in match (eptr=<optimized out>, ecode=0x4e84d49 "\205", mstart=0x4e9ce03 "https://xxxxxxxx.xxxx.xx:oooo/XxxxxXxxxxxx/Xxxxxxxx/Xxxxxxxxxxx oooo-oo-oo oo:oo:oo oooo [xxxoxxxxxxx.XxxxxxxxXxxxxxxx] Xxxxxxxxxxx XXX xxxxxxxx xxxxxxxxx oooo-oo-oo oo:oo:oo oooo [xxxoxxxxxxx.Xxxxxxx"..., offset_top=4, md=0x7fffffffca00, eptrb=0x0, rdepth=<optimized out>) at pcre_exec.c:983 #15877 0x00007fffe4250591 in pcre_exec (argument_re=0x4e84c20, extra_data=<optimized out>, subject=<optimized out>, length=26884, start_offset=0, options=9216, offsets=0x4e11010, offsetcount=9) at pcre_exec.c:6936 #15878 0x00007ffff352b4eb in g_match_info_next () at /lib64/libglib-2.0.so.0 #15879 0x00007ffff352cd9f in g_regex_match_full () at /lib64/libglib-2.0.so.0 #15880 0x00007ffff352d84c in g_regex_replace_eval () at /lib64/libglib-2.0.so.0 #15881 0x00007ffff77ea7b9 in parse_html_into_blocks (view=0x364c770, document=0x4e62050, parent=0x7fffc81cfce0, passed_block_template=0x0, html=0x4e96350 "Xx xxxx xx xxxxxx. Xxx Xxxxxxxxxxx xxxx xxx xxx xx xxx Xxxxxxxxx ", 'x' <repeats 11 times>, " xxxxxxxxüxxx.<br>Xxx XXX xxx: https://xxxxxxxx.xxxx.xx:oooo/XxxxxXxxxxxx/Xxxxxxxx/Xxxxxxxxxxx<br>Xxxxxxxx xxx xxx xxx Xxxx"...) at e-html-editor-view.c:7485 #15882 0x00007ffff77ecb24 in html_editor_convert_view_content (view=0x364c770, preferred_text=0x0) at e-html-editor-view.c:8249 #15883 0x00007ffff77f56e5 in html_editor_view_load_status_changed (view=0x364c770) at e-html-editor-view.c:10860 #15884 0x00007ffff37ee3e8 in g_closure_invoke () at /lib64/libgobject-2.0.so.0 #15885 0x00007ffff3800442 in signal_emit_unlocked_R () at /lib64/libgobject-2.0.so.0 #15886 0x00007ffff380908c in g_signal_emit_valist () at /lib64/libgobject-2.0.so.0 #15887 0x00007ffff380945f in g_signal_emit () at /lib64/libgobject-2.0.so.0 #15888 0x00007ffff37f27b4 in g_object_dispatch_properties_changed () at /lib64/libgobject-2.0.so.0 #15889 0x00007ffff37f4cc4 in g_object_notify () at /lib64/libgobject-2.0.so.0 #15890 0x00007ffff5253adf in WebCore::FrameLoader::checkLoadCompleteForThisFrame() () at /lib64/libwebkitgtk-3.0.so.0 #15891 0x00007ffff5253cb7 in WebCore::FrameLoader::checkLoadComplete() () at /lib64/libwebkitgtk-3.0.so.0 #15892 0x00007ffff523dd38 in WebCore::DocumentLoader::finishedLoading(double) () at /lib64/libwebkitgtk-3.0.so.0 #15893 0x00007ffff523ec0c in WebCore::DocumentLoader::continueAfterContentPolicy(WebCore::PolicyAction) () at /lib64/libwebkitgtk-3.0.so.0 #15894 0x00007ffff523fcc4 in WebCore::DocumentLoader::responseReceived(WebCore::CachedResource*, WebCore::ResourceResponse const&) () at /lib64/libwebkitgtk-3.0.so.0 #15895 0x00007ffff5239f77 in WebCore::DocumentLoader::handleSubstituteDataLoadNow(WebCore::Timer<WebCore::DocumentLoader>*) () at /lib64/libwebkitgtk-3.0.so.0 #15896 0x00007ffff4bfad5f in WebCore::ThreadTimers::sharedTimerFiredInternal() () at /lib64/libwebkitgtk-3.0.so.0 #15897 0x00007ffff4c1ee32 in WebCore::sharedTimerTimeoutCallback(void*) () at /lib64/libwebkitgtk-3.0.so.0 #15898 0x00007ffff351a273 in g_timeout_dispatch () at /lib64/libglib-2.0.so.0 #15899 0x00007ffff3519803 in g_main_context_dispatch () at /lib64/libglib-2.0.so.0 #15900 0x00007ffff3519bb0 in g_main_context_iterate.isra () at /lib64/libglib-2.0.so.0 #15901 0x00007ffff3519ed2 in g_main_loop_run () at /lib64/libglib-2.0.so.0 #15902 0x00007ffff3fd2825 in gtk_main () at gtkmain.c:1269 #15903 0x0000000000403de6 in main (argc=1, argv=0x7fffffffdcf8) at main.c:660 This is taken from the 3.18.5, because it is easier. The frames between #3 and #15873 all look the same, just like the #3 or the #15873.
Tomas, could you check our regular expressions, please? Maybe we've there something odd. If you do not find, then we can move this to the pcre package, where the recursion happens. For the record: (gdb) f 3 #3 0x00007fffe424c662 in match (eptr=<optimized out>, ecode=0x4e84d65 "y", mstart=0x4e9ce03 "https://xxxxxxxx.xxxx.xx:oooo/XxxxxXxxxxxx/Xxxxxxxx/Xxxxxxxxxxx oooo-oo-oo oo:oo:oo oooo [xxxoxxxxxxx.XxxxxxxxXxxxxxxx] Xxxxxxxxxxx XXX xxxxxxxx xxxxxxxxx oooo-oo-oo oo:oo:oo oooo [xxxoxxxxxxx.Xxxxxxx"..., offset_top=4, md=0x7fffffffca00, eptrb=0x0, rdepth=<optimized out>) at pcre_exec.c:2061 2061 RMATCH(eptr, prev, offset_top, md, eptrb, RM13); (gdb) l 2056 ecode = prev; 2057 goto TAIL_RECURSE; 2058 } 2059 else /* OP_KETRMAX */ 2060 { 2061 RMATCH(eptr, prev, offset_top, md, eptrb, RM13); 2062 if (rrc == MATCH_ONCE && md->once_target == prev) rrc = MATCH_NOMATCH; 2063 if (rrc != MATCH_NOMATCH) RRETURN(rrc); 2064 if (*prev == OP_ONCE) 2065 { (gdb)
I don't see anything obvious, thus moving to pcre.
It looks like exhausted stack. Some regular expressions on some inputs have pathological backtracking path that leads to enormous recursion and your default 8 MB large stack gets exhausted. This is feature of stack-based recursive algorithms and PCRE can do with. You can either rewrite your regular expression to use less recursion (less greedy and less possessive atoms), or you can limit the recursion depth by setting match_limit_recursion member of pcre_exec() second argument, or you can increase stack size of your process. I recommend you to read pcrestack(3) manual page and to use pcretest tool for debugging your regular expression with your input. Unfortunately, you did not provide any of them in this bug report.
Created attachment 1197148 [details] regex.c Here's a simple reproducer, which makes it crash on the stack overflow out of the evolution code. The first line of the file shows how to compile and run it.
It starts segfaulting with 14085 KB stack in Fedora 26. But it segfaults randomly. On Fedora 23, it does not segfault, but it also prints "---(null)---". Something different from Fedora 26 where it prints the input. I thought it's because of newer pcre. But F26 and F23 have the same pcre package. So I thought it's because of newer GCC having more aggressive optimization or bigger stack frames. But your reproducer uses glib2 functions. Not pcre functions directly. And glib2 package version also differs and indeed rebuilding F23 glib2 in F26 provides the same F23 experience -- no crash, no string printed. I will have to nail down the reproducer to pcre only.
That's because F23 glib2 bundles pcre-8.31.
I can reproduce it with pcre only. It happens when matching the input from offset 180. It's because of the second expression part "((?:(?! ).)*)". It consumes a lot of stack because the greedy * operator recurses on each character for a case when some other expression part failed. And because the recursion happens on each character of the input, the stack exhaustion exhibits on very long lines like in your reproducer (there is a 25908-character long line, that's 25908 recursions, each consumes about 500 B of a stack, that agrees with the observed 14-MB limit.). Solution is to make the * operator possesive by changing it into "*+" operator. It changes the preceding group into an atomic group which must match the longest sequence of the content of the group. In other words it says to pcre that it does not need to examine substrings of non-" "-character string. If you want to know more, read "ATOMIC GROUPING AND POSSESSIVE QUANTIFIERS" section in pcrepattern(3) manual page. Try changing two lines in the reproducer into: #define URL_PATTERN_BASE "(?=((?:(?:(?:" URL_PROTOCOLS ")\\:\\/\\/)|(?:www\\.|ftp\\.))[^\\s\\/\\$\\.\\?#].[^\\s]*+)" #define URL_PATTERN_NO_NBSP ")((?:(?! ).)*+)" It adds "+" after the "*" on two places.
Thanks a lot for all the investigation. I changed the regex locally and I do not see any difference, except of surviving evolution, instead of crashing. The evolution also uses an email pattern: /* http://www.w3.org/TR/html5/forms.html#valid-e-mail-address */ #define E_MAIL_PATTERN \ "[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}"\ "[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*" To which I'll add the '+' too, just in case. By the way, would not it be a regression in pcre that 8.31 works, but 8.39 crashes?
I'm making this bug public, there is nothing private after all. Created commit 4163018 in evo master (3.21.92+) [1] [1] https://git.gnome.org/browse/evolution/commit/?id=4163018
The old glib2 with bundled pcre does not crash. But also does not return correct result. I don't know why. I tried the pure pcre reproducer against Fedora's pcre-8.31 and it crashed.
(In reply to Petr Pisar from comment #16) > The old glib2 with bundled pcre does not crash. But also does not return > correct result. I don't know why. I tried the pure pcre reproducer against > Fedora's pcre-8.31 and it crashed. Aha, good... I mean... :)