FS#76144 - [stardict] stardict segfault frequently

Attached to Project: Community Packages
Opened by Lin Xiao (xiaoliniess) - Saturday, 08 October 2022, 18:48 GMT
Last edited by Buggy McBugFace (bugbot) - Saturday, 25 November 2023, 20:04 GMT
Task Type Bug Report
Category Packages
Status Closed
Assigned To Felix Yan (felixonmars)
Architecture All
Severity Low
Priority Normal
Reported Version
Due in Version Undecided
Due Date Undecided
Percent Complete 100%
Votes 0
Private No

Details

Description:
stardict segfault frequently due to uninitialized pointer from stardict-youdaodict-plugin

Additional info:
Affected Version: 3.0.6.2-1

Steps to reproduce:
1.start stardict
2.enter random long string in the search field which is unlikely to be a real word(e.g. 'aaafdsfdsdfsfaasfda')
3.delete and reenter some chars back and forth repeatedly
4.stardict will segfault very quickly
This task depends upon

Closed by  Buggy McBugFace (bugbot)
Saturday, 25 November 2023, 20:04 GMT
Reason for closing:  Moved
Additional comments about closing:  https://gitlab.archlinux.org/archlinux/p ackaging/packages/stardict/issues/1
Comment by Lin Xiao (xiaoliniess) - Saturday, 08 October 2022, 18:51 GMT
This bug can be reproduced on ubuntu latest stardict package.
This problem can be fixed by deleting the youdaodict-plugin.
As upstream is not very active, I suggest skip installing the plugin in arch package as a temporary fix.
Comment by Toolybird (Toolybird) - Sunday, 09 October 2022, 01:31 GMT
For segfaults, it's best to try and get a debug trace if possible. For this particular case, the plugin would need to be recompiled with debug symbols as the current trace is not much use (see attached).

   gdb.txt (1.8 KiB)
Comment by Lin Xiao (xiaoliniess) - Sunday, 09 October 2022, 02:13 GMT
I tried that and event did some live debuging. I believe I've found the root cause of the segfault.
In following function from dict/stardict-plugins/stardict-youdaodict-plugin/stardict_youdaodict.cpp

################################################################################
static void on_get_http_response(const char *buffer, size_t buffer_len, gpointer userdata)
{
if (!buffer) {
return;
}
const char *p = g_strstr_len(buffer, buffer_len, "\r\n\r\n");
if (!p) {
return;
}
p += 4;

QueryInfo *qi = (QueryInfo *)userdata;
NetDictResponse *resp = new NetDictResponse; <============================ Here, a new instance of NetDictResponse is created
resp->bookname = _("www.YouDao.com");
resp->booklink = "http://www.youdao.com";
resp->word = qi->word; // So neen't free qi->word;

process_xml_response(p, buffer_len - (p - buffer), resp); <================= The "data" field is supposed to be initialized in this function.

plugin_service->netdict_save_cache_resp(YOUDAODICT, qi->word, resp);
plugin_service->show_netdict_resp(YOUDAODICT, resp, qi->ismainwin);
delete qi;
keyword_list.remove(qi);
}
###############################################################################

But if the word is invalid, there won't be any search results. process_xml_response could return without setting the "data" field in resp. And no check against it.
In "void TextWin::Show(NetDictResponse *resp)" function from dict/src/mainwin.cpp, it actually checked the "data" pointer before using it.

###############################################################################
void TextWin::Show(NetDictResponse *resp)
{
view->begin_update();
bool do_append;
if (query_result == TEXT_WIN_FOUND || query_result == TEXT_WIN_SHOW_FIRST || query_result == TEXT_WIN_NET_FOUND || query_result == TEXT_WIN_NET_SHOW_FIRST) {
do_append = true;
view->goto_end();
} else {
do_append = false;
view->clear();
view->goto_begin();
}
if (resp->data) { <========================= Here, the "data" pointer is checked before use
query_result = TEXT_WIN_NET_FOUND;
InstantDictIndex dict_index;
dict_index.type = InstantDictType_UNKNOWN;
view->SetDictIndex(dict_index);
gchar *mark = g_strdup_printf("%d", view->get_bookindex());
gpAppFrame->oMidWin.oIndexWin.oResultWin.InsertLast(resp->bookname, mark);
g_free(mark);
view->AppendHeader(resp->bookname, resp->booklink);
view->AppendWord(resp->word);
view->AppendData(resp->data, resp->word, resp->word);
view->AppendNewline();
} else {
if (!do_append) {
query_result = TEXT_WIN_NET_NOT_FOUND;
Show(_("<Not Found!>"));
}
}
view->end_update();
}
#################################################################################
But as the "data" pointer is not initialized. It's random, not NULL. It will be used and trigger segfault.

So a possible fix is setting the data pointer to NULL in the first function I mentioned. I just tested the patch attached. No segfault anymore.

Loading...