Ticket #3705 (closed defect: invalid)
Reproducible segfault in Find File dialog
Reported by: | zaytsev | Owned by: | |
---|---|---|---|
Priority: | major | Milestone: | 4.8.19 |
Component: | mc-search | Version: | 4.8.18 |
Keywords: | Cc: | egmont | |
Blocked By: | Blocking: | ||
Branch state: | no branch | Votes for changeset: |
Description
I'm able to reliably crash the latest release while searching in Python sources for the following:
╔══════════════════════════ Find File ═══════════════════════════╗ ║ Start at: ║ ║ . [^] [ Tree ] ║ ║ [ ] Enable ignore directories: ║ ║ .git:.hg:.svn:build [^] ║ ╟────────────────────────────────────────────────────────────────╢ ║ File name: Content: ║ ║ * [^] python-config [^] ║ ║ [x] Find recursively [x] Whole words ║ ║ [x] Using shell patterns [ ] Regular expression ║ ║ [ ] Case sensitive [x] Case sensitive ║ ║ [ ] All charsets [ ] All charsets ║ ║ [ ] Skip hidden [ ] First hit ║ ╟────────────────────────────────────────────────────────────────╢ ║ [< OK >] [ Cancel ] ║ ╚════════════════════════════════════════════════════════════════╝
To reproduce:
- wget https://www.python.org/ftp/python/2.7.12/Python-2.7.12.tar.xz
- tar xvf Python-2.7.12.tar.xz
- cd Python-2.7.12
- mc
- Search as specified, observe a segfault.
Backtraces:
Program terminated with signal 11, Segmentation fault. #0 0x000000317241d907 in _pcre_xclass () from /lib/libpcre.so.3 (gdb) bt #0 0x000000317241d907 in _pcre_xclass () from /lib/libpcre.so.3 #1 0x00000031724111b5 in ?? () from /lib/libpcre.so.3 #2 0x0000003172412051 in ?? () from /lib/libpcre.so.3 #3 0x000000317241ad64 in pcre_exec () from /lib/libpcre.so.3 #4 0x00000031728562c1 in g_match_info_next () from /lib/libglib-2.0.so.0 #5 0x00000031728564e3 in g_regex_match_full () from /lib/libglib-2.0.so.0 #6 0x0000000000480ae5 in mc_search__g_regex_match_full_safe (regex=0x1f59650, string=0x1f7a600 "\213l$H\213\\$4A\203\375xt5A\203\375pt/@\017\266\317\350\025g\377\377\063\311;\301\017\204\224", string_len=36, start_position=0, match_options=G_REGEX_MATCH_NEWLINE_ANY, match_info=0x1f79a48, error=0x7fff8e4b0588) at ../../../lib/search/regex.c:270 #7 0x0000000000480c3f in mc_search__regex_found_cond_one (lc_mc_search=0x1f79a00, regex=0x1f59650, search_str=0x1f41640) at ../../../lib/search/regex.c:317 #8 0x0000000000480d4f in mc_search__regex_found_cond (lc_mc_search=0x1f79a00, search_str=0x1f41640) at ../../../lib/search/regex.c:366 #9 0x000000000048201e in mc_search__run_regex (lc_mc_search=0x1f79a00, user_data=0x1f7d9e0, start_search=0, end_search=36, found_len=0x7fff8e4b07f8) at ../../../lib/search/regex.c:944 #10 0x000000000047ec01 in mc_search__run_normal (lc_mc_search=0x1f79a00, user_data=0x1f7d9e0, start_search=0, end_search=36, found_len=0x7fff8e4b07f8) at ../../../lib/search/normal.c:104 #11 0x000000000044f685 in mc_search_run (lc_mc_search=0x1f79a00, user_data=0x1f7d9e0, start_search=0, end_search=36, found_len=0x7fff8e4b07f8) at ../../../lib/search/search.c:295 #12 0x00000000004c2051 in search_content (h=0x1f31900, directory=0x1f76fc0 "/home/zaytsev/src/python/Python-2.7.12/Lib/distutils/command", filename=0x1f58cc3 "wininst-9.0-amd64.exe") at ../../../src/filemanager/find.c:1112 #13 0x00000000004c2a17 in do_search (h=0x1f31900) at ../../../src/filemanager/find.c:1386 #14 0x00000000004c2f93 in find_callback (w=0x1f31900, sender=0x0, msg=MSG_IDLE, parm=0, data=0x0) at ../../../src/filemanager/find.c:1531 #15 0x000000000041c66f in send_message (w=0x1f31900, sender=0x0, msg=MSG_IDLE, parm=0, data=0x0) at ../../../lib/widget/widget-common.h:209 #16 0x000000000041d253 in frontend_dlg_run (h=0x1f31900) at ../../../lib/widget/dialog.c:528 #17 0x000000000041e7c6 in dlg_run (h=0x1f31900) at ../../../lib/widget/dialog.c:1196 #18 0x00000000004c3697 in run_process () at ../../../src/filemanager/find.c:1687 #19 0x00000000004c37cf in do_find (start_dir=0x1f40220 "/home/zaytsev/src/python/Python-2.7.12", start_dir_len=38, ignore_dirs=0x0, pattern=0x1f31750 "*", content=0x1f6d280 "python-config", dirname=0x7fff8e4b2000, filename=0x7fff8e4b2008) at ../../../src/filemanager/find.c:1728 #20 0x00000000004c3dee in find_file () at ../../../src/filemanager/find.c:1862 #21 0x00000000004b5b8c in find_cmd () at ../../../src/filemanager/cmd.c:936 #22 0x000000000043d793 in midnight_execute_cmd (sender=0x0, command=105) at ../../../src/filemanager/midnight.c:1209 #23 0x000000000043e019 in midnight_callback (w=0x1f395d0, sender=0x0, msg=MSG_UNHANDLED_KEY, parm=8255, data=0x0) at ../../../src/filemanager/midnight.c:1544 #24 0x000000000041c66f in send_message (w=0x1f395d0, sender=0x0, msg=MSG_UNHANDLED_KEY, parm=8255, data=0x0) at ../../../lib/widget/widget-common.h:209 #25 0x000000000041d141 in dlg_key_event (h=0x1f395d0, d_key=8255) at ../../../lib/widget/dialog.c:489 #26 0x000000000041e706 in dlg_process_event (h=0x1f395d0, key=8255, event=0x7fff8e4b21d0) at ../../../lib/widget/dialog.c:1165 #27 0x000000000041d2d9 in frontend_dlg_run (h=0x1f395d0) at ../../../lib/widget/dialog.c:541 #28 0x000000000041e7c6 in dlg_run (h=0x1f395d0) at ../../../lib/widget/dialog.c:1196 #29 0x000000000043d1a8 in create_panels_and_run_mc () at ../../../src/filemanager/midnight.c:952 #30 0x000000000043e826 in do_nc () at ../../../src/filemanager/midnight.c:1768 #31 0x000000000040f717 in main (argc=1, argv=0x7fff8e4b23d8) at ../../src/main.c:403 (gdb) bt full #0 0x000000317241d907 in _pcre_xclass () from /lib/libpcre.so.3 No symbol table info available. #1 0x00000031724111b5 in ?? () from /lib/libpcre.so.3 No symbol table info available. #2 0x0000003172412051 in ?? () from /lib/libpcre.so.3 No symbol table info available. #3 0x000000317241ad64 in pcre_exec () from /lib/libpcre.so.3 No symbol table info available. #4 0x00000031728562c1 in g_match_info_next () from /lib/libglib-2.0.so.0 No symbol table info available. #5 0x00000031728564e3 in g_regex_match_full () from /lib/libglib-2.0.so.0 No symbol table info available. #6 0x0000000000480ae5 in mc_search__g_regex_match_full_safe (regex=0x1f59650, string=0x1f7a600 "\213l$H\213\\$4A\203\375xt5A\203\375pt/@\017\266\317\350\025g\377\377\063\311;\301\017\204\224", string_len=36, start_position=0, match_options=G_REGEX_MATCH_NEWLINE_ANY, match_info=0x1f79a48, error=0x7fff8e4b0588) at ../../../lib/search/regex.c:270 string_safe = 0x40 <Address 0x40 out of bounds> p = 0x3170f7fe40 "" end = 0x0 ret = 0 #7 0x0000000000480c3f in mc_search__regex_found_cond_one (lc_mc_search=0x1f79a00, regex=0x1f59650, search_str=0x1f41640) at ../../../lib/search/regex.c:317 mcerror = 0x0 #8 0x0000000000480d4f in mc_search__regex_found_cond (lc_mc_search=0x1f79a00, search_str=0x1f41640) at ../../../lib/search/regex.c:366 mc_search_cond = 0x1f59520 ret = COND__NOT_FOUND loop1 = 0 #9 0x000000000048201e in mc_search__run_regex (lc_mc_search=0x1f79a00, user_data=0x1f7d9e0, start_search=0, end_search=36, found_len=0x7fff8e4b07f8) at ../../../lib/search/regex.c:944 ret = MC_SEARCH_CB_NOTFOUND current_pos = 36 virtual_pos = 36 start_pos = 0 end_pos = 0 #10 0x000000000047ec01 in mc_search__run_normal (lc_mc_search=0x1f79a00, user_data=0x1f7d9e0, start_search=0, end_search=36, found_len=0x7fff8e4b07f8) at ../../../lib/search/normal.c:104 No locals. #11 0x000000000044f685 in mc_search_run (lc_mc_search=0x1f79a00, user_data=0x1f7d9e0, start_search=0, end_search=36, found_len=0x7fff8e4b07f8) at ../../../lib/search/search.c:295 ret = 0 #12 0x00000000004c2051 in search_content (h=0x1f31900, directory=0x1f76fc0 "/home/zaytsev/src/python/Python-2.7.12/Lib/distutils/command", filename=0x1f58cc3 "wininst-9.0-amd64.exe") at ../../../src/filemanager/find.c:1112 ch = 0 '\000' line = 192 pos = 2079 found = 0 found_len = 13 found_start = 42750 n_read = 4096 off = 88058 strbuf_size = 256 result = "\000\000@\000\000\000\000\000\025\000\000\000\000\000\000\000P\225\365\001\000\000\000\000\260\224\365\001", '\000' <repeats 12 times>, " \025\364\001\000\000\000\000\200\266\367\001\000\000\000\000\060\360@\000\000\000\000\000\320#K\216\377\177\000\000P\225\365\001\000\000\000\000\000\031K\216\377\177\000\000\335\fH\000\000\000\000\000\350\030K\216\377\177\000\000Ì\365\001\000\000\000\000 \031K\216\377\177\000\000\240\207\367\001\000\000\000\000\260\224\365\001\000\000\000\000\220\232\367\001\000\000\000\000\320#K\216\377\177\000\000\000\000\000\000\000\000\000\000\240\207\367\001\000\000\000\000Ì\365\001\000\000\000\000@\031K\216\377\177\000\000O\rH\000\000\000\000\000\240\207\367\001\000\000\000\000\220\232\367\001\000\000\000\000\300\031K\216\377\177\000\000\060\372\367\001", '\000' <repeats 16 times>, "\004\000\000\000\300\031K\216\377\177\000\000E H\000\000\000\000\000p\031K\216\377\177\000\000\070\033K\216\377\177"... strbuf = 0x1f7d9e0 "\213l$H\213\\$4A\203\375xt5A\203\375pt/@\017\266\317\350\025g\377\377\063\311;\301\017\204\224" i = 36 s = {st_dev = 20, st_ino = 1411177, st_nlink = 1, st_mode = 33188, st_uid = 1000, st_gid = 1000, __pad0 = 0, st_rdev = 0, st_size = 223744, st_blksize = 4096, st_blocks = 456, st_atim = {tv_sec = 1476990802, tv_nsec = 272561009}, st_mtim = { tv_sec = 1466891370, tv_nsec = 0}, st_ctim = {tv_sec = 1476990796, tv_nsec = 202056713}, __unused = {0, 0, 0}} buffer = "6\001\000\000\213\305+\351A;\307\017\204)\001\000\000H\213D$pL\215\214$\020\001\000\000L\215D$p\306\004\003eH\003\331H\215D$|H\215\224$\240\000\000\000H\213\313H\211D$ \350\234\367\377\377A;\307\017\204\302\t\000\000I\213\314A\377\305\350T\370\377\377\213\370\211D$<\203\370-u>H\213D$pL\215\214$\020\001\000\000L\215D$p@\210<\003H\215D$|H\377\303H\215\224$\240\000\000\000H\213\313H\211D$ \350J\367\377\377A;\307\017\204p\t\000\000\353\005\203\370+u$\213Ź\001\000\000\000+\351A;\307u\005A\213\357\353\021D\003\351I\213\314\350\350\367\377\377\213\370\211D$<@\017\266\317\353`\213Ź\001\000\000\000+\351A;\307t\\H\213D$p\003\361L\215\214$\020\001\000\000@\210<\003H\003\331H\215D$|L\215D$pH\215\224$\240\000\000\000H\213\313H\211D$ \350\315\366\377\377A;\307\017\204\363\b\000\000I\213\314A\377\305\350\205\367\377\377\213\370\211D$<\017\266\310\350\367m\377\377A;\307u\226\270\001\000\000\000D+\350D\211l$4A;\376t\017I\213"... file_fd = 101 ret_val = 0 vpath = 0x1f79310 tv = {tv_sec = 1476991628, tv_usec = 667463} seconds = 0 useconds = 28731 status_updated = 0 #13 0x00000000004c2a17 in do_search (h=0x1f31900) at ../../../src/filemanager/find.c:1386 search_ok = 1 dp = 0x1f58cb0 dirp = 0x1f78fe0 directory = 0x1f76fc0 "/home/zaytsev/src/python/Python-2.7.12/Lib/distutils/command" tmp_stat = {st_dev = 20, st_ino = 1411177, st_nlink = 1, st_mode = 33188, st_uid = 1000, st_gid = 1000, __pad0 = 0, st_rdev = 0, st_size = 223744, st_blksize = 4096, st_blocks = 456, st_atim = {tv_sec = 1476990802, tv_nsec = 272561009}, st_mtim = {tv_sec = 1466891370, tv_nsec = 0}, st_ctim = {tv_sec = 1476990796, tv_nsec = 202056713}, __unused = {0, 0, 0}} bytes_found = 21 count = 21 #14 0x00000000004c2f93 in find_callback (w=0x1f31900, sender=0x0, msg=MSG_IDLE, parm=0, data=0x0) at ../../../src/filemanager/find.c:1531 h = 0x1f31900 #15 0x000000000041c66f in send_message (w=0x1f31900, sender=0x0, msg=MSG_IDLE, parm=0, data=0x0) at ../../../lib/widget/widget-common.h:209 ret = MSG_NOT_HANDLED #16 0x000000000041d253 in frontend_dlg_run (h=0x1f31900) at ../../../lib/widget/dialog.c:528 d_key = 0 wh = 0x1f31900 event = {buttons = 1, x = -1, y = 32708864, type = 0} #17 0x000000000041e7c6 in dlg_run (h=0x1f31900) at ../../../lib/widget/dialog.c:1196 No locals. #18 0x00000000004c3697 in run_process () at ../../../src/filemanager/find.c:1687 ret = 0 #19 0x00000000004c37cf in do_find (start_dir=0x1f40220 "/home/zaytsev/src/python/Python-2.7.12", start_dir_len=38, ignore_dirs=0x0, pattern=0x1f31750 "*", content=0x1f6d280 "python-config", dirname=0x7fff8e4b2000, filename=0x7fff8e4b2008) at ../../../src/filemanager/find.c:1728 return_value = 0 dir_tmp = 0x0 file_tmp = 0x0 #20 0x00000000004c3dee in find_file () at ../../../src/filemanager/find.c:1862 filename = 0x0 dirname = 0x0 v = 1 start_dir = 0x1f40220 "/home/zaytsev/src/python/Python-2.7.12" pattern = 0x1f31750 "*" content = 0x1f6d280 "python-config" ignore_dirs = 0x0 start_dir_len = 38 #21 0x00000000004b5b8c in find_cmd () at ../../../src/filemanager/cmd.c:936 No locals. #22 0x000000000043d793 in midnight_execute_cmd (sender=0x0, command=105) at ../../../src/filemanager/midnight.c:1209 res = MSG_HANDLED #23 0x000000000043e019 in midnight_callback (w=0x1f395d0, sender=0x0, msg=MSG_UNHANDLED_KEY, parm=8255, data=0x0) at ../../../src/filemanager/midnight.c:1544 v = MSG_NOT_HANDLED command = 105 #24 0x000000000041c66f in send_message (w=0x1f395d0, sender=0x0, msg=MSG_UNHANDLED_KEY, parm=8255, data=0x0) at ../../../lib/widget/widget-common.h:209 ret = MSG_NOT_HANDLED #25 0x000000000041d141 in dlg_key_event (h=0x1f395d0, d_key=8255) at ../../../lib/widget/dialog.c:489 handled = MSG_NOT_HANDLED #26 0x000000000041e706 in dlg_process_event (h=0x1f395d0, key=8255, event=0x7fff8e4b21d0) at ../../../lib/widget/dialog.c:1165 No locals. #27 0x000000000041d2d9 in frontend_dlg_run (h=0x1f395d0) at ../../../lib/widget/dialog.c:541 d_key = 8255 wh = 0x1f395d0 event = {buttons = 5128754, x = -1, y = 32740816, type = 0} #28 0x000000000041e7c6 in dlg_run (h=0x1f395d0) at ../../../lib/widget/dialog.c:1196 No locals. #29 0x000000000043d1a8 in create_panels_and_run_mc () at ../../../src/filemanager/midnight.c:952 No locals. #30 0x000000000043e826 in do_nc () at ../../../src/filemanager/midnight.c:1768 ret = 49 #31 0x000000000040f717 in main (argc=1, argv=0x7fff8e4b23d8) at ../../src/main.c:403 mcerror = 0x0 config_migrated = 0 config_migrate_msg = 0x4dcfd5 "H\205\355t\034\061\333\353\002\220\220L\211\372L\211\366D\211\357A\377\024\334H\203\303\001H9\353r\352H\213\\$\bH\213l$\020L\213d$\030L\213l$ L\213t$(L\213|$0H\203\304\070Ð\220\220\220\220\220\220H\211\362H\211\376\277\001" exit_code = 1 (gdb)
Change History
comment:2 Changed 8 years ago by zaytsev
- Cc egmont added
The problem is in the search engine and not directly related to the Find File dialog: if one opens Python-2.7.12/Lib/distutils/command/wininst-9.0.exe and searches in the viewer or editor for anything with [x] Whole words enabled, it will crash.
$ locale LANG=en_US.UTF-8
comment:3 Changed 8 years ago by zaytsev
Sounds like something very much reminiscent of #3449, apparently mc_search__g_regex_match_full_safe isn't all that safe after all :-(
comment:4 Changed 8 years ago by egmont
It does not crash for me.
I'm on Ubuntu Yakkety (glib 2.50.0, libpcre3 8.39), tried mc 4.8.17 as shipped by the distro, as well as current git.
I executed mcview wininst-9.0.exe and searched for strings like "foo" (there is a match), "foobar", "asdf" and similar ones. "Whole words" enabled; tried normal as well as regex mode. Locale is also en_US.UTF-8.
Based on the stack trace I suspect a bug in your libpcre3. What version do you have of it?
Could you please add some debugging to your mc_search__g_regex_match_full_safe() so that it records in some binary-safe way the string/string_safe (and string_len) parameters that it passes to g_regex_match_full() so that we can manually examine whether it's valid UTF-8?
comment:5 follow-up: ↓ 6 Changed 8 years ago by zaytsev
Based on the stack trace I suspect a bug in your libpcre3. What version do you have of it?
Oh, it's many years out of date, my version is libpcre3 8.02 and glib 2.26.1. Okay, I can try to upgrade libpcre3 to the next release and see if it goes away. It could be also likewise a bug in glib though :-/ both are way too old. Sigh...
Could you please add some debugging to your mc_search__g_regex_match_full_safe() so that it records in some binary-safe way the string/string_safe (and string_len) parameters that it passes to g_regex_match_full()
Well, you have it in the full backtrace, right? Apparently it goes into the first branch, thinking it's valid. I will see if I can get time to investigate some more...
Thank you for your feedback! That it doesn't crash on a newer system is a very important piece of information.
comment:6 in reply to: ↑ 5 Changed 8 years ago by egmont
Replying to zaytsev:
Well, you have it in the full backtrace, right? Apparently it goes into the first branch, thinking it's valid.
That would be a problem, because the string is clearly invalid UTF-8. How can you tell from the backtrace that is goes to the first branch? I don't think you can tell it.
comment:7 follow-up: ↓ 8 Changed 8 years ago by zaytsev-work
My line of thinking was that in the backtrace string_safe = 0x40, which could mean that it's not initialised properly, as in when the first branch is taken, but, of course, you are right that one should build in additional logging instead of engaging in further speculation. In the mean time, I can confirm that it doesn't segfault on Debian 8 (current stable) :-/
comment:8 in reply to: ↑ 7 Changed 8 years ago by egmont
Replying to zaytsev-work:
My line of thinking was that in the backtrace string_safe = 0x40
I just noticed there was a "bt full" section as well after "bt" :)
How to read this format? Does this string_safe = 0x40 refer to the moment when g_regex_match_full() is called? Could gcc optimization tamper with these values?
Yeah let's do some additional poor man's (printf-style) debugging.
comment:10 Changed 8 years ago by zaytsev
Just built pcre-8.39.tar.gz from source and installed in /opt/pcre:
../configure --with-search-engine=pcre --with-pcre=/opt/pcre
So, apparently, it's a bug in pcre and/or glib, which was fixed in later releases. The fact that it crashes in _pcre_xclass () was hinting at it, but the question of whether it's being passed valid data was an open one. Now, it's clear that the call is valid, and the problem is really somewhere inside pcre and/or glib.
Thanks everybody and sorry for the noise! I will build with newer pcre from now on...
comment:11 Changed 8 years ago by zaytsev
- Status changed from new to closed
- Resolution set to invalid
The crash happens only if [x] Whole words is ticked.