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:
@@ -33,7 +33,7 @@ static struct color_pair_cache
|
||||
{
|
||||
struct
|
||||
{
|
||||
int16_t fg, bg;
|
||||
short fg, bg;
|
||||
}* pairs;
|
||||
int size;
|
||||
int capacity;
|
||||
@@ -315,14 +315,18 @@ color_distance(const struct color_def* a, const struct color_def* b)
|
||||
return h * h + s * s + l * l;
|
||||
}
|
||||
|
||||
static int
|
||||
/* Indices into the 256-colour palette and ncurses palette IDs are
|
||||
* 16-bit (the size_t-or-short distinction in ncurses init_pair).
|
||||
* Use `short` end-to-end so the caller boundaries don't need casts.
|
||||
*/
|
||||
static short
|
||||
find_closest_col(int h, int s, int l)
|
||||
{
|
||||
struct color_def a = { h, s, l, NULL };
|
||||
int min = 0;
|
||||
struct color_def a = { (uint16_t)h, (uint8_t)s, (uint8_t)l, NULL };
|
||||
short min = 0;
|
||||
int dmin = color_distance(&a, &color_names[0]);
|
||||
|
||||
for (int i = 1; i < COLOR_NAME_SIZE; i++) {
|
||||
for (short i = 1; i < COLOR_NAME_SIZE; i++) {
|
||||
int d = color_distance(&a, &color_names[i]);
|
||||
if (d < dmin) {
|
||||
dmin = d;
|
||||
@@ -332,8 +336,8 @@ find_closest_col(int h, int s, int l)
|
||||
return min;
|
||||
}
|
||||
|
||||
static int
|
||||
find_col(const char* col_name, int n)
|
||||
static short
|
||||
find_col(const char* col_name, size_t n)
|
||||
{
|
||||
char name[32] = { 0 };
|
||||
|
||||
@@ -343,9 +347,9 @@ find_col(const char* col_name, int n)
|
||||
* blue.
|
||||
*/
|
||||
|
||||
if (n >= (int)sizeof(name)) {
|
||||
if (n >= sizeof(name)) {
|
||||
/* truncate */
|
||||
log_error("Color: <%s,%d> bigger than %zu", col_name, n, sizeof(name));
|
||||
log_error("Color: <%s,%zu> bigger than %zu", col_name, n, sizeof(name));
|
||||
n = sizeof(name) - 1;
|
||||
}
|
||||
memcpy(name, col_name, n);
|
||||
@@ -354,7 +358,7 @@ find_col(const char* col_name, int n)
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < COLOR_NAME_SIZE; i++) {
|
||||
for (short i = 0; i < COLOR_NAME_SIZE; i++) {
|
||||
if (g_ascii_strcasecmp(name, color_names[i].name) == 0) {
|
||||
return i;
|
||||
}
|
||||
@@ -363,13 +367,13 @@ find_col(const char* col_name, int n)
|
||||
return COL_ERR;
|
||||
}
|
||||
|
||||
static int
|
||||
static short
|
||||
color_hash(const char* str, color_profile profile)
|
||||
{
|
||||
GChecksum* cs = NULL;
|
||||
guint8 buf[256] = { 0 };
|
||||
gsize len = 256;
|
||||
int rc = -1; /* default ncurse color */
|
||||
short rc = -1; /* default ncurse color */
|
||||
|
||||
cs = g_checksum_new(G_CHECKSUM_SHA1);
|
||||
if (!cs)
|
||||
@@ -438,7 +442,7 @@ color_pair_cache_reset(void)
|
||||
}
|
||||
|
||||
static int
|
||||
_color_pair_cache_get(int fg, int bg)
|
||||
_color_pair_cache_get(short fg, short bg)
|
||||
{
|
||||
if (COLORS < 256) {
|
||||
if (fg > 7 || bg > 7) {
|
||||
@@ -463,10 +467,13 @@ _color_pair_cache_get(int fg, int bg)
|
||||
}
|
||||
|
||||
int i = cache.size;
|
||||
// TODO: init_pair uses 15-bit palette indices. Terminals exposing
|
||||
// extended colour palettes (>32767) need init_extended_pair here.
|
||||
// Upstream-inherited limitation.
|
||||
cache.pairs[i].fg = fg;
|
||||
cache.pairs[i].bg = bg;
|
||||
/* (re-)define the new pair in curses */
|
||||
init_pair(i, fg, bg);
|
||||
init_pair((short)i, fg, bg);
|
||||
|
||||
cache.size++;
|
||||
|
||||
@@ -485,8 +492,8 @@ _color_pair_cache_get(int fg, int bg)
|
||||
int
|
||||
color_pair_cache_hash_str(const char* str, color_profile profile)
|
||||
{
|
||||
int fg = color_hash(str, profile);
|
||||
int bg = -1;
|
||||
short fg = color_hash(str, profile);
|
||||
short bg = -1;
|
||||
|
||||
auto_char char* bkgnd = theme_get_bkgnd();
|
||||
if (bkgnd) {
|
||||
@@ -506,7 +513,7 @@ int
|
||||
color_pair_cache_get(const char* pair_name)
|
||||
{
|
||||
const char* sep;
|
||||
int fg, bg;
|
||||
short fg, bg;
|
||||
|
||||
sep = strchr(pair_name, '_');
|
||||
if (!sep) {
|
||||
@@ -514,7 +521,7 @@ color_pair_cache_get(const char* pair_name)
|
||||
return -1;
|
||||
}
|
||||
|
||||
fg = find_col(pair_name, sep - pair_name);
|
||||
fg = find_col(pair_name, (size_t)(sep - pair_name));
|
||||
bg = find_col(sep + 1, strlen(sep));
|
||||
if (fg == COL_ERR || bg == COL_ERR) {
|
||||
log_error("Color: bad color name %s", pair_name);
|
||||
|
||||
Reference in New Issue
Block a user