refactor: clean narrowing conversions and harden unsigned arithmetic
Cleanup of the conversion-safety warnings exposed by enabling -Wconversion / -Wsign-compare in the previous commit, plus guard clauses at the few places where unsigned arithmetic could actually misbehave. Build: - configure.ac drops -Wno-error=conversion and -Wno-error=float-conversion. Only -Wno-error=sign-conversion and -Wno-error=sign-compare remain, gating the ~230 sign warnings inherited from upstream that will be cleaned up in follow-ups. Type / conversion fixes (no behaviour change): - Length-like locals in command/cmd_ac.c, command/cmd_funcs.c, pgp/gpg.c, tools/autocomplete.c, tools/parser.c and ui/mucwin.c switched from int to size_t / glong (matching strlen / g_utf8_strlen return type) so we no longer need an (int) cast and loop counters / array sizes stay in their natural unsigned domain. - g_timer_elapsed / GTimeSpan -> int casts in session.c, iq.c, core.c, server_events.c, window.c. - _win_print_wrapped: indent parameter and local curx/maxx switched from size_t to int to match _win_indent / getcurx / getmaxx. - Port casts (int -> unsigned short) at the libstrophe boundary in connection.c and session.c, each preceded by g_assert(port >= 0 && port <= UINT16_MAX) so the truncation is documented at the call-site. - curl_off_t / fread size_t results cast at usage in http_upload.c, http_download.c, omemo/crypto.c. - strtoul results cast to uint32_t in xmpp/omemo.c and omemo/omemo.c where device/prekey IDs are genuinely 32-bit. - config/color.c: fg/bg/palette indices switched to `short` end-to-end (find_col, color_hash, find_closest_col, _color_pair_cache_get, cache.pairs), so the ncurses init_pair boundary needs at most one (short)i cast for the cache index. Also TODO-noted: init_extended_pair is needed for >15-bit palettes. - xmpp/avatar.c: float arithmetic explicitly casts its int operands. - tests/functionaltests/proftest.c: read() result handling uses size_t for the accumulator, _read_output returns ssize_t, and the buffer-shift check happens before space subtraction so the expression cannot underflow. Real-risk guard clauses (the part that actually fixes bugs): - src/ui/statusbar.c _tabs_width: `end > opened_tabs - 1` rewritten as `end < opened_tabs` so opened_tabs == 0 no longer underflows. - src/ui/statusbar.c _status_bar_draw_extended_tabs: the mirror comparison rewritten as `end >= opened_tabs`. - src/ui/statusbar.c status_bar_draw: replaced `MAX(0, getmaxx - (int)_tabs_width)` with an explicit precheck before subtraction. - src/omemo/omemo.c prekey selection: prekey_index is now uint32_t and randomized into an unsigned buffer, so modulo with prekeys_len cannot yield a negative index for g_list_nth_data. - src/omemo/crypto.c omemo_decrypt_func: PKCS#5/PKCS#7 unpadding reads `plaintext[plaintext_len - 1]`, which would underflow on a malformed empty ciphertext and read past the heap buffer. Reject plaintext_len == 0 before the padding peek and validate the padding byte against the buffer length before the unpad loop. Initialise plaintext = NULL so the early `goto out` cannot free uninitialised memory. - src/ui/inputwin.c (4 mbrlen sites) and src/ui/window.c _win_print_wrapped: mbrlen() returns 0 for the null wide character. The existing checks rejected (size_t)-1 / -2 but treated 0 as a valid step, so the surrounding loops would either advance by SIZE_MAX (i += ch_len - 1) or spin in place (word_pos += 0 forever). Add `|| ch_len == 0` to each guard; inside the spell-check word-emission loop also fall back to a one-byte advance. - Defensive `len > 0 ? len - 1 : 0` prechecks at the strlen-based g_strndup / loop sites in ui/console.c, plugins/c_api.c and plugins/python_plugins.c.
This commit is contained in:
@@ -92,8 +92,11 @@ cons_show_help(const char* const cmd, CommandHelp* help)
|
||||
win_println(console, THEME_HELP_HEADER, "-", "%s", &cmd[1]);
|
||||
win_print(console, THEME_HELP_HEADER, "-", "");
|
||||
size_t i;
|
||||
for (i = 0; i < strlen(cmd) - 1; i++) {
|
||||
win_append(console, THEME_HELP_HEADER, "-");
|
||||
size_t cmd_len = strlen(cmd);
|
||||
if (cmd_len > 0) {
|
||||
for (i = 0; i < cmd_len - 1; i++) {
|
||||
win_append(console, THEME_HELP_HEADER, "-");
|
||||
}
|
||||
}
|
||||
win_appendln(console, THEME_HELP_HEADER, "");
|
||||
cons_show("");
|
||||
@@ -115,7 +118,7 @@ cons_show_help(const char* const cmd, CommandHelp* help)
|
||||
cons_show("");
|
||||
win_println(console, THEME_HELP_HEADER, "-", "Arguments");
|
||||
for (i = 0; help->args[i][0] != NULL; i++) {
|
||||
win_println_indent(console, maxlen + 3, "%-*s: %s", (int)(maxlen + 1), help->args[i][0], help->args[i][1]);
|
||||
win_println_indent(console, (int)(maxlen + 3), "%-*s: %s", (int)(maxlen + 1), help->args[i][0], help->args[i][1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -166,7 +166,7 @@ ui_get_idle_time(void)
|
||||
// if no libxss or xss idle time failed, use profanity idle time
|
||||
#endif
|
||||
gdouble seconds_elapsed = g_timer_elapsed(ui_idle_time, NULL);
|
||||
unsigned long ms_elapsed = seconds_elapsed * 1000.0;
|
||||
unsigned long ms_elapsed = (unsigned long)(seconds_elapsed * 1000.0);
|
||||
return ms_elapsed;
|
||||
}
|
||||
|
||||
|
||||
@@ -385,7 +385,10 @@ _inp_write(char* line, int offset)
|
||||
char retc[PROF_MB_CUR_MAX] = { 0 };
|
||||
|
||||
size_t ch_len = mbrlen(c, MB_CUR_MAX, NULL);
|
||||
if ((ch_len == (size_t)-2) || (ch_len == (size_t)-1)) {
|
||||
// ch_len == 0 means mbrlen consumed the null wide character;
|
||||
// skipping it here keeps `i += ch_len - 1` below from
|
||||
// underflowing to SIZE_MAX.
|
||||
if ((ch_len == (size_t)-2) || (ch_len == (size_t)-1) || ch_len == 0) {
|
||||
waddch(inp_win, ' ');
|
||||
continue;
|
||||
}
|
||||
@@ -409,7 +412,9 @@ _inp_write(char* line, int offset)
|
||||
size_t end = start + ch_len;
|
||||
while (line[end] != '\0') {
|
||||
size_t next_ch_len = mbrlen(&line[end], MB_CUR_MAX, NULL);
|
||||
if (next_ch_len == (size_t)-2 || next_ch_len == (size_t)-1)
|
||||
// ch_len == 0 means embedded NUL — stop, otherwise
|
||||
// `end += next_ch_len` loops forever.
|
||||
if (next_ch_len == (size_t)-2 || next_ch_len == (size_t)-1 || next_ch_len == 0)
|
||||
break;
|
||||
gunichar next_uc = g_utf8_get_char(&line[end]);
|
||||
if (!g_unichar_isalnum(next_uc) && next_uc != '\'')
|
||||
@@ -428,7 +433,13 @@ _inp_write(char* line, int offset)
|
||||
size_t word_pos = start;
|
||||
while (word_pos < end) {
|
||||
size_t cur_ch_len = mbrlen(&line[word_pos], MB_CUR_MAX, NULL);
|
||||
waddnstr(inp_win, &line[word_pos], cur_ch_len);
|
||||
// Defensive: invalid or zero-length step would loop
|
||||
// forever; advance one byte and continue.
|
||||
if (cur_ch_len == (size_t)-2 || cur_ch_len == (size_t)-1 || cur_ch_len == 0) {
|
||||
word_pos++;
|
||||
continue;
|
||||
}
|
||||
waddnstr(inp_win, &line[word_pos], (int)cur_ch_len);
|
||||
word_pos += cur_ch_len;
|
||||
}
|
||||
|
||||
@@ -441,7 +452,7 @@ _inp_write(char* line, int offset)
|
||||
}
|
||||
}
|
||||
|
||||
waddnstr(inp_win, c, ch_len);
|
||||
waddnstr(inp_win, c, (int)ch_len);
|
||||
}
|
||||
|
||||
wmove(inp_win, 0, col);
|
||||
@@ -494,11 +505,13 @@ _inp_offset_to_col(char* str, int offset)
|
||||
while (i < offset && str[i] != '\0') {
|
||||
gunichar uni = g_utf8_get_char(&str[i]);
|
||||
size_t ch_len = mbrlen(&str[i], MB_CUR_MAX, NULL);
|
||||
if ((ch_len == (size_t)-2) || (ch_len == (size_t)-1)) {
|
||||
// ch_len == 0 (embedded NUL) would freeze the loop on the same
|
||||
// byte; treat it like an invalid step.
|
||||
if ((ch_len == (size_t)-2) || (ch_len == (size_t)-1) || ch_len == 0) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
i += ch_len;
|
||||
i += (int)ch_len;
|
||||
col++;
|
||||
if (g_unichar_iswide(uni)) {
|
||||
col++;
|
||||
|
||||
@@ -382,7 +382,7 @@ _mucwin_print_mention(ProfWin* window, const char* const message, const char* co
|
||||
auto_gchar gchar* mynick_str = g_utf8_substring(message, pos, pos + mynick_len);
|
||||
win_append_highlight(window, THEME_ROOMMENTION_TERM, "%s", mynick_str);
|
||||
|
||||
last_pos = pos + mynick_len;
|
||||
last_pos = pos + (int)mynick_len;
|
||||
|
||||
curr = g_slist_next(curr);
|
||||
}
|
||||
@@ -400,8 +400,8 @@ _mucwin_print_mention(ProfWin* window, const char* const message, const char* co
|
||||
gint
|
||||
_cmp_trigger_weight(gconstpointer a, gconstpointer b)
|
||||
{
|
||||
int alen = strlen((char*)a);
|
||||
int blen = strlen((char*)b);
|
||||
size_t alen = strlen((char*)a);
|
||||
size_t blen = strlen((char*)b);
|
||||
|
||||
if (alen > blen)
|
||||
return -1;
|
||||
@@ -438,10 +438,10 @@ _mucwin_print_triggers(ProfWin* window, const char* const message, GList* trigge
|
||||
}
|
||||
|
||||
// found, replace vars if earlier than previous
|
||||
int trigger_pos = trigger_ptr - message_lower;
|
||||
int trigger_pos = (int)(trigger_ptr - message_lower);
|
||||
if (first_trigger_pos == -1 || trigger_pos < first_trigger_pos) {
|
||||
first_trigger_pos = trigger_pos;
|
||||
first_trigger_len = strlen(trigger_lower);
|
||||
first_trigger_len = (int)strlen(trigger_lower);
|
||||
}
|
||||
|
||||
curr = g_list_next(curr);
|
||||
|
||||
@@ -304,8 +304,13 @@ _status_bar_draw_tabs(guint pos)
|
||||
gboolean is_static = g_strcmp0(tabmode, "dynamic") != 0;
|
||||
_get_range_bounds(&start, &end, is_static);
|
||||
|
||||
// if the result of the calc is negative we take 0
|
||||
pos = MAX(0, (getmaxx(stdscr) - (int)_tabs_width(start, end)));
|
||||
guint tabs_w = _tabs_width(start, end);
|
||||
int max_x = getmaxx(stdscr);
|
||||
if (max_x > 0 && (guint)max_x > tabs_w) {
|
||||
pos = (guint)max_x - tabs_w;
|
||||
} else {
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
pos = _status_bar_draw_extended_tabs(pos, TRUE, start, end, is_static);
|
||||
|
||||
@@ -392,7 +397,9 @@ _status_bar_draw_extended_tabs(guint pos, gboolean prefix, guint start, guint en
|
||||
if (prefix && start < 2) {
|
||||
return pos;
|
||||
}
|
||||
if (!prefix && end > opened_tabs - 1) {
|
||||
// Guard against underflow when opened_tabs == 0 (reachable if the
|
||||
// earlier `opened_tabs <= max_tabs` early-return no longer holds).
|
||||
if (!prefix && end >= opened_tabs) {
|
||||
return pos;
|
||||
}
|
||||
gboolean is_current = is_static && statusbar->current_tab > max_tabs;
|
||||
@@ -504,7 +511,7 @@ _status_bar_draw_time(guint pos)
|
||||
int bracket_attrs = theme_attrs(THEME_STATUS_BRACKET);
|
||||
int time_attrs = theme_attrs(THEME_STATUS_TIME);
|
||||
|
||||
size_t len = strlen(statusbar->time);
|
||||
guint len = (guint)strlen(statusbar->time);
|
||||
wattron(statusbar_win, bracket_attrs);
|
||||
mvwaddch(statusbar_win, 0, pos, '[');
|
||||
pos++;
|
||||
@@ -599,7 +606,7 @@ _tabs_width(guint start, guint end)
|
||||
guint opened_tabs = g_hash_table_size(statusbar->tabs);
|
||||
|
||||
int width = start < 2 ? 1 : 4;
|
||||
width += end > opened_tabs - 1 ? 0 : 3;
|
||||
width += (end < opened_tabs) ? 3 : 0;
|
||||
|
||||
if (show_name && show_number) {
|
||||
for (guint i = start; i <= end; i++) {
|
||||
|
||||
@@ -224,7 +224,7 @@ _title_bar_draw(void)
|
||||
auto_gchar gchar* title = win_get_title(current);
|
||||
|
||||
mvwprintw(win, 0, 0, " %s", title);
|
||||
pos = strlen(title) + 1;
|
||||
pos = (int)strlen(title) + 1;
|
||||
|
||||
// presence is written from the right side
|
||||
// calculate it first so we have a maxposition
|
||||
@@ -596,7 +596,7 @@ _show_contact_presence(ProfChatWin* chatwin, int pos, int maxpos)
|
||||
}
|
||||
|
||||
if (resource && prefs_get_boolean(PREF_RESOURCE_TITLE)) {
|
||||
int needed = strlen(resource) + 1;
|
||||
int needed = (int)strlen(resource) + 1;
|
||||
if (pos + needed < maxpos) {
|
||||
wprintw(win, "/");
|
||||
wprintw(win, "%s", resource);
|
||||
|
||||
@@ -75,7 +75,7 @@ static void
|
||||
_win_printf(ProfWin* window, const char* show_char, int pad_indent, GDateTime* timestamp, int flags, theme_item_t theme_item, const char* const display_from, const char* const from_jid, const char* const message_id, const char* const message, ...);
|
||||
static void _win_print_internal(ProfWin* window, const char* show_char, int pad_indent, GDateTime* time,
|
||||
int flags, theme_item_t theme_item, const char* const from, const char* const message, DeliveryReceipt* receipt);
|
||||
static void _win_print_wrapped(WINDOW* win, const char* const message, size_t indent, int pad_indent);
|
||||
static void _win_print_wrapped(WINDOW* win, const char* const message, int indent, int pad_indent);
|
||||
|
||||
// Helper: clamp a subwindow width to a sane range [1, cols-1] if possible
|
||||
static int
|
||||
@@ -1048,11 +1048,11 @@ win_show_contact(ProfWin* window, PContact contact)
|
||||
GTimeSpan span = g_date_time_difference(now, last_activity);
|
||||
g_date_time_unref(now);
|
||||
|
||||
int hours = span / G_TIME_SPAN_HOUR;
|
||||
int hours = (int)(span / G_TIME_SPAN_HOUR);
|
||||
span = span - hours * G_TIME_SPAN_HOUR;
|
||||
int minutes = span / G_TIME_SPAN_MINUTE;
|
||||
int minutes = (int)(span / G_TIME_SPAN_MINUTE);
|
||||
span = span - minutes * G_TIME_SPAN_MINUTE;
|
||||
int seconds = span / G_TIME_SPAN_SECOND;
|
||||
int seconds = (int)(span / G_TIME_SPAN_SECOND);
|
||||
|
||||
if (hours > 0) {
|
||||
win_append(window, presence_colour, ", idle %dh%dm%ds", hours, minutes, seconds);
|
||||
@@ -1173,11 +1173,11 @@ win_show_info(ProfWin* window, PContact contact)
|
||||
GDateTime* now = g_date_time_new_now_local();
|
||||
GTimeSpan span = g_date_time_difference(now, last_activity);
|
||||
|
||||
int hours = span / G_TIME_SPAN_HOUR;
|
||||
int hours = (int)(span / G_TIME_SPAN_HOUR);
|
||||
span = span - hours * G_TIME_SPAN_HOUR;
|
||||
int minutes = span / G_TIME_SPAN_MINUTE;
|
||||
int minutes = (int)(span / G_TIME_SPAN_MINUTE);
|
||||
span = span - minutes * G_TIME_SPAN_MINUTE;
|
||||
int seconds = span / G_TIME_SPAN_SECOND;
|
||||
int seconds = (int)(span / G_TIME_SPAN_SECOND);
|
||||
|
||||
if (hours > 0) {
|
||||
win_println(window, THEME_DEFAULT, "-", "Last activity: %dh%dm%ds", hours, minutes, seconds);
|
||||
@@ -1846,7 +1846,7 @@ _win_print_internal(ProfWin* window, const char* show_char, int pad_indent, GDat
|
||||
gboolean me_message = FALSE;
|
||||
int offset = 0;
|
||||
int colour = theme_attrs(THEME_ME);
|
||||
size_t indent = 0;
|
||||
int indent = 0;
|
||||
|
||||
auto_gchar gchar* time_pref = NULL;
|
||||
switch (window->type) {
|
||||
@@ -1879,7 +1879,7 @@ _win_print_internal(ProfWin* window, const char* show_char, int pad_indent, GDat
|
||||
assert(date_fmt != NULL);
|
||||
|
||||
if (strlen(date_fmt) != 0) {
|
||||
indent = 3 + strlen(date_fmt);
|
||||
indent = 3 + (int)strlen(date_fmt);
|
||||
}
|
||||
|
||||
if ((flags & NO_DATE) == 0) {
|
||||
@@ -1975,7 +1975,7 @@ _win_indent(WINDOW* win, int size)
|
||||
}
|
||||
|
||||
static void
|
||||
_win_print_wrapped(WINDOW* win, const char* const message, size_t indent, int pad_indent)
|
||||
_win_print_wrapped(WINDOW* win, const char* const message, int indent, int pad_indent)
|
||||
{
|
||||
int starty = getcury(win);
|
||||
int wordi = 0;
|
||||
@@ -2002,7 +2002,8 @@ _win_print_wrapped(WINDOW* win, const char* const message, size_t indent, int pa
|
||||
int wordlen = 0;
|
||||
while (*curr_ch != ' ' && *curr_ch != '\n' && *curr_ch != '\0') {
|
||||
size_t ch_len = mbrlen(curr_ch, MB_CUR_MAX, NULL);
|
||||
if ((ch_len == (size_t)-2) || (ch_len == (size_t)-1)) {
|
||||
// 0 / invalid step: advance one byte to avoid spinning.
|
||||
if ((ch_len == (size_t)-2) || (ch_len == (size_t)-1) || ch_len == 0) {
|
||||
curr_ch++;
|
||||
continue;
|
||||
}
|
||||
@@ -2015,9 +2016,9 @@ _win_print_wrapped(WINDOW* win, const char* const message, size_t indent, int pa
|
||||
word[wordi] = '\0';
|
||||
wordlen = utf8_display_len(word);
|
||||
|
||||
size_t curx = (size_t)getcurx(win);
|
||||
int curx = getcurx(win);
|
||||
int cury;
|
||||
size_t maxx = getmaxx(win);
|
||||
int maxx = getmaxx(win);
|
||||
|
||||
// wrap required
|
||||
if (curx + wordlen > maxx) {
|
||||
@@ -2027,7 +2028,7 @@ _win_print_wrapped(WINDOW* win, const char* const message, size_t indent, int pa
|
||||
if (wordlen > linelen) {
|
||||
gchar* word_ch = g_utf8_offset_to_pointer(word, 0);
|
||||
while (*word_ch != '\0') {
|
||||
curx = (size_t)getcurx(win);
|
||||
curx = getcurx(win);
|
||||
cury = getcury(win);
|
||||
gboolean firstline = cury == starty;
|
||||
|
||||
@@ -2048,7 +2049,7 @@ _win_print_wrapped(WINDOW* win, const char* const message, size_t indent, int pa
|
||||
// newline and print word
|
||||
} else {
|
||||
waddch(win, '\n');
|
||||
curx = (size_t)getcurx(win);
|
||||
curx = getcurx(win);
|
||||
cury = getcury(win);
|
||||
gboolean firstline = cury == starty;
|
||||
|
||||
@@ -2063,7 +2064,7 @@ _win_print_wrapped(WINDOW* win, const char* const message, size_t indent, int pa
|
||||
|
||||
// no wrap required
|
||||
} else {
|
||||
curx = (size_t)getcurx(win);
|
||||
curx = getcurx(win);
|
||||
cury = getcury(win);
|
||||
gboolean firstline = cury == starty;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user