mirror of
https://github.com/irssi/irssi.git
synced 2026-08-21 17:42:49 +02:00
CRITICAL FIX: Resolve infinite recursion causing segfault
Problem: Debug printtext() in format_get_text_theme_charargs() caused infinite recursion: 1. format_get_text_theme_charargs() calls printtext() for debug 2. printtext() formats timestamp calling textbuffer_line_get_text() 3. textbuffer_line_get_text() calls format_get_text_theme_charargs() again 4. Infinite recursion → stack overflow → segfault Solution: Replace printtext() with printf() in format debug to avoid recursion Stack trace showed 100+ recursive calls to format_get_text_theme_charargs() This explains segfaults during highlights when focus was on status window. Timestamp: 2025-01-25 01:15
This commit is contained in:
parent
ad0d88b123
commit
0a40fac215
3 changed files with 71 additions and 51 deletions
|
|
@ -319,7 +319,7 @@ settings = {
|
||||||
theme = "default.theme";
|
theme = "default.theme";
|
||||||
nick_column_enabled = "yes";
|
nick_column_enabled = "yes";
|
||||||
nick_column_width = "10";
|
nick_column_width = "10";
|
||||||
debug_nick_column = "no";
|
debug_nick_column = "yes";
|
||||||
};
|
};
|
||||||
"fe-text" = {
|
"fe-text" = {
|
||||||
lag_min_show = "1s";
|
lag_min_show = "1s";
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,8 @@
|
||||||
#include <irssip/src/core/expandos.h>
|
#include <irssip/src/core/expandos.h>
|
||||||
#include <irssip/src/fe-common/core/fe-windows.h>
|
#include <irssip/src/fe-common/core/fe-windows.h>
|
||||||
#include <irssip/src/core/settings.h>
|
#include <irssip/src/core/settings.h>
|
||||||
|
#include <irssip/src/fe-common/core/printtext.h>
|
||||||
|
#include <irssip/src/core/levels.h>
|
||||||
|
|
||||||
/* Nick column context variables */
|
/* Nick column context variables */
|
||||||
static char *current_nick = NULL;
|
static char *current_nick = NULL;
|
||||||
|
|
@ -100,7 +102,8 @@ static char *expando_nickalign(SERVER_REC *server, void *item, int *free_ret)
|
||||||
|
|
||||||
/* Debug output */
|
/* Debug output */
|
||||||
if (settings_get_bool("debug_nick_column")) {
|
if (settings_get_bool("debug_nick_column")) {
|
||||||
printf("DEBUG nickalign: nick='%s', mode='%s', width=%d, mode_chars=%d, nick_chars=%d, total_chars=%d, padding=%d\n",
|
printtext(NULL, NULL, MSGLEVEL_CLIENTCRAP,
|
||||||
|
"DEBUG nickalign: nick='%s', mode='%s', width=%d, mode_chars=%d, nick_chars=%d, total_chars=%d, padding=%d",
|
||||||
current_nick, mode, width, mode_chars, nick_chars, total_chars, padding);
|
current_nick, mode, width, mode_chars, nick_chars, total_chars, padding);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -115,6 +118,15 @@ static char *expando_nicktrunc(SERVER_REC *server, void *item, int *free_ret)
|
||||||
const char *mode;
|
const char *mode;
|
||||||
char *result;
|
char *result;
|
||||||
|
|
||||||
|
/* Debug entry */
|
||||||
|
if (settings_get_bool("debug_nick_column")) {
|
||||||
|
printtext(NULL, NULL, MSGLEVEL_CLIENTCRAP,
|
||||||
|
"DEBUG nicktrunc CALLED: enabled=%s, valid=%s, nick='%s'",
|
||||||
|
settings_get_bool("nick_column_enabled") ? "yes" : "no",
|
||||||
|
nick_context_valid ? "yes" : "no",
|
||||||
|
current_nick ? current_nick : "NULL");
|
||||||
|
}
|
||||||
|
|
||||||
/* Gdy wyłączone - zwróć oryginalny nick */
|
/* Gdy wyłączone - zwróć oryginalny nick */
|
||||||
if (!settings_get_bool("nick_column_enabled")) {
|
if (!settings_get_bool("nick_column_enabled")) {
|
||||||
return current_nick ? current_nick : "";
|
return current_nick ? current_nick : "";
|
||||||
|
|
@ -140,7 +152,8 @@ static char *expando_nicktrunc(SERVER_REC *server, void *item, int *free_ret)
|
||||||
result = g_strdup_printf("%.*s>>", available_for_nick, current_nick);
|
result = g_strdup_printf("%.*s>>", available_for_nick, current_nick);
|
||||||
|
|
||||||
if (settings_get_bool("debug_nick_column")) {
|
if (settings_get_bool("debug_nick_column")) {
|
||||||
printf("DEBUG nicktrunc TRUNCATED: original='%s', truncated='%s', available_for_nick=%d\n",
|
printtext(NULL, NULL, MSGLEVEL_CLIENTCRAP,
|
||||||
|
"DEBUG nicktrunc TRUNCATED: original='%s', truncated='%s', available_for_nick=%d",
|
||||||
current_nick, result, available_for_nick);
|
current_nick, result, available_for_nick);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -148,13 +161,19 @@ static char *expando_nicktrunc(SERVER_REC *server, void *item, int *free_ret)
|
||||||
result = g_strdup(">>");
|
result = g_strdup(">>");
|
||||||
|
|
||||||
if (settings_get_bool("debug_nick_column")) {
|
if (settings_get_bool("debug_nick_column")) {
|
||||||
printf("DEBUG nicktrunc MODE_TOO_LONG: result='%s'\n", result);
|
printtext(NULL, NULL, MSGLEVEL_CLIENTCRAP,
|
||||||
|
"DEBUG nicktrunc MODE_TOO_LONG: result='%s'", result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*free_ret = TRUE;
|
*free_ret = TRUE;
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
/* Nick się zmieści - zwróć oryginalny */
|
/* Nick się zmieści - zwróć oryginalny */
|
||||||
|
if (settings_get_bool("debug_nick_column")) {
|
||||||
|
printtext(NULL, NULL, MSGLEVEL_CLIENTCRAP,
|
||||||
|
"DEBUG nicktrunc NO_TRUNCATION: nick='%s', total_chars=%d <= width=%d",
|
||||||
|
current_nick, total_chars, width);
|
||||||
|
}
|
||||||
return current_nick;
|
return current_nick;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
#include <irssip/src/fe-common/core/window-items.h>
|
#include <irssip/src/fe-common/core/window-items.h>
|
||||||
#include <irssip/src/fe-common/core/formats.h>
|
#include <irssip/src/fe-common/core/formats.h>
|
||||||
#include <irssip/src/fe-common/core/themes.h>
|
#include <irssip/src/fe-common/core/themes.h>
|
||||||
|
#include <irssip/src/fe-common/core/printtext.h>
|
||||||
#include <irssip/src/core/recode.h>
|
#include <irssip/src/core/recode.h>
|
||||||
#include <irssip/src/core/utf8.h>
|
#include <irssip/src/core/utf8.h>
|
||||||
#include <irssip/src/core/misc.h>
|
#include <irssip/src/core/misc.h>
|
||||||
|
|
@ -837,61 +838,55 @@ static gboolean is_message_format(int formatnum)
|
||||||
formatnum == TXT_PUBMSG_HILIGHT || formatnum == TXT_PUBMSG_HILIGHT_CHANNEL);
|
formatnum == TXT_PUBMSG_HILIGHT || formatnum == TXT_PUBMSG_HILIGHT_CHANNEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Apply nick column formatting to format string */
|
/* Get nick parameter number for specific format */
|
||||||
static char *apply_nick_column_formatting(const char *format)
|
static int get_nick_param_for_format(int formatnum)
|
||||||
{
|
{
|
||||||
GString *result;
|
switch (formatnum) {
|
||||||
char *modified;
|
case TXT_OWN_MSG:
|
||||||
char *pos, *before, *after, *temp;
|
case TXT_OWN_MSG_CHANNEL:
|
||||||
|
case TXT_PUBMSG:
|
||||||
|
case TXT_PUBMSG_CHANNEL:
|
||||||
|
case TXT_PUBMSG_ME:
|
||||||
|
case TXT_PUBMSG_ME_CHANNEL:
|
||||||
|
return 0; /* $0 = nick */
|
||||||
|
|
||||||
|
case TXT_PUBMSG_HILIGHT:
|
||||||
|
case TXT_PUBMSG_HILIGHT_CHANNEL:
|
||||||
|
return 1; /* $1 = nick (because $0 = color) */
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0; /* fallback */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Apply nick column formatting to format string */
|
||||||
|
static char *apply_nick_column_formatting(const char *format, int formatnum)
|
||||||
|
{
|
||||||
|
char *result;
|
||||||
|
char *pos, *before, *after;
|
||||||
|
char search_param[10], replace_param[20];
|
||||||
|
int nick_param;
|
||||||
|
|
||||||
if (!format) return NULL;
|
if (!format) return NULL;
|
||||||
|
|
||||||
result = g_string_new("");
|
/* Get correct parameter number for nick in this format */
|
||||||
|
nick_param = get_nick_param_for_format(formatnum);
|
||||||
|
g_snprintf(search_param, sizeof(search_param), "${%d}", nick_param);
|
||||||
|
g_snprintf(replace_param, sizeof(replace_param), "${nicktrunc}");
|
||||||
|
|
||||||
/* Add $nickalign at the beginning if not already present */
|
/* Replace ${X} with ${nicktrunc} where X is the nick parameter */
|
||||||
if (!strstr(format, "$nickalign")) {
|
pos = strstr(format, search_param);
|
||||||
g_string_append(result, "$nickalign");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Replace nick templates with truncated versions */
|
|
||||||
modified = g_strdup(format);
|
|
||||||
|
|
||||||
/* Replace {ownnick $0} with {ownnick $nicktrunc} */
|
|
||||||
pos = strstr(modified, "{ownnick $0}");
|
|
||||||
if (pos) {
|
if (pos) {
|
||||||
before = g_strndup(modified, pos - modified);
|
before = g_strndup(format, pos - format);
|
||||||
after = pos + strlen("{ownnick $0}");
|
after = pos + strlen(search_param);
|
||||||
g_free(modified);
|
result = g_strdup_printf("$nickalign%s%s%s", before, replace_param, after);
|
||||||
modified = g_strdup_printf("%s{ownnick $nicktrunc}%s", before, after);
|
|
||||||
g_free(before);
|
g_free(before);
|
||||||
|
} else {
|
||||||
|
/* No replacement needed, just add nickalign */
|
||||||
|
result = g_strdup_printf("$nickalign%s", format);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Replace {pubnick $0} with {pubnick $nicktrunc} */
|
return result;
|
||||||
pos = strstr(modified, "{pubnick $0}");
|
|
||||||
if (pos) {
|
|
||||||
before = g_strndup(modified, pos - modified);
|
|
||||||
after = pos + strlen("{pubnick $0}");
|
|
||||||
temp = modified;
|
|
||||||
modified = g_strdup_printf("%s{pubnick $nicktrunc}%s", before, after);
|
|
||||||
g_free(temp);
|
|
||||||
g_free(before);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Replace {menick $0} with {menick $nicktrunc} */
|
|
||||||
pos = strstr(modified, "{menick $0}");
|
|
||||||
if (pos) {
|
|
||||||
before = g_strndup(modified, pos - modified);
|
|
||||||
after = pos + strlen("{menick $0}");
|
|
||||||
temp = modified;
|
|
||||||
modified = g_strdup_printf("%s{menick $nicktrunc}%s", before, after);
|
|
||||||
g_free(temp);
|
|
||||||
g_free(before);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_string_append(result, modified);
|
|
||||||
g_free(modified);
|
|
||||||
|
|
||||||
return g_string_free_and_steal(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char *format_get_text_theme_charargs(THEME_REC *theme, const char *module,
|
char *format_get_text_theme_charargs(THEME_REC *theme, const char *module,
|
||||||
|
|
@ -915,8 +910,14 @@ char *format_get_text_theme_charargs(THEME_REC *theme, const char *module,
|
||||||
if (settings_get_bool("nick_column_enabled") &&
|
if (settings_get_bool("nick_column_enabled") &&
|
||||||
g_strcmp0(module, "fe-common/core") == 0 &&
|
g_strcmp0(module, "fe-common/core") == 0 &&
|
||||||
is_message_format(formatnum)) {
|
is_message_format(formatnum)) {
|
||||||
modified_text = apply_nick_column_formatting(text);
|
modified_text = apply_nick_column_formatting(text, formatnum);
|
||||||
text = modified_text;
|
text = modified_text;
|
||||||
|
|
||||||
|
/* Debug output - use printf to avoid recursion */
|
||||||
|
if (settings_get_bool("debug_nick_column")) {
|
||||||
|
printf("DEBUG format_auto: formatnum=%d, original='%s'\n", formatnum, module_theme->expanded_formats[formatnum]);
|
||||||
|
printf("DEBUG format_auto: modified='%s'\n", text);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result = format_get_text_args(dest, text, args);
|
result = format_get_text_args(dest, text, args);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue