fix(ui,db): harden NULL handling, fix CWE-134, optimize iterations
Some checks failed
CI Code / Code Coverage (push) Failing after 10m34s
CI Code / Check spelling (push) Failing after 10m47s
CI Code / Check coding style (push) Failing after 11m4s
CI Code / Linux (ubuntu) (push) Failing after 11m19s
CI Code / Linux (debian) (push) Failing after 11m28s
CI Code / Linux (arch) (push) Failing after 11m38s

security(CWE-134): fix format string injections + add CI check
fix(ui): subwindow lifecycle, newwin/newpad guards, fallback timestamps
fix(db): sqlite cleanup on failures, sqlite3_close_v2
fix(xmpp): queued_messages loop, barejid leak
perf(core): g_hash_table_iter_init instead of g_hash_table_get_keys
refactor(ui): CLAMP macro in _check_subwin_width
test: XEP-0012 and XEP-0045 functional tests

Author: jabber.developer2
Closes #58, #85
This commit is contained in:
2026-02-06 19:27:40 +01:00
parent f8826b7c79
commit 467222d0ca
36 changed files with 656 additions and 238 deletions

View File

@@ -184,7 +184,7 @@ _string_matches_one_of(const char* what, const char* is, bool is_can_be_null, co
}
va_end(ap);
if (s > 0)
cons_show(errmsg);
cons_show("%s", errmsg);
}
return ret;
}
@@ -418,7 +418,7 @@ cmd_connect(ProfWin* window, const char* const command, gchar** args)
auto_char char* err_msg = NULL;
gboolean res = strtoi_range(port_str, &port, 1, 65535, &err_msg);
if (!res) {
cons_show(err_msg);
cons_show("%s", err_msg);
cons_show("");
port = 0;
options_destroy(options);
@@ -711,7 +711,7 @@ _account_set_port(char* account_name, char* port)
auto_char char* err_msg = NULL;
gboolean res = strtoi_range(port, &porti, 1, 65535, &err_msg);
if (!res) {
cons_show(err_msg);
cons_show("%s", err_msg);
cons_show("");
} else {
accounts_set_port(account_name, porti);
@@ -903,7 +903,7 @@ _account_set_max_sessions(char* account_name, char* max_sessions_raw)
auto_char char* err_msg = NULL;
gboolean res = strtoi_range(max_sessions_raw, &max_sessions, 0, INT_MAX, &err_msg);
if (!res) {
cons_show(err_msg);
cons_show("%s", err_msg);
cons_show("");
return TRUE;
}
@@ -924,7 +924,7 @@ _account_set_presence_priority(char* account_name, char* presence, char* priorit
auto_char char* err_msg = NULL;
gboolean res = strtoi_range(priority, &intval, -128, 127, &err_msg);
if (!res) {
cons_show(err_msg);
cons_show("%s", err_msg);
return TRUE;
}
@@ -1580,7 +1580,7 @@ _cmd_list_commands(GList* commands)
while (curr) {
gchar* cmd = curr->data;
if (count == 5) {
cons_show(cmds->str);
cons_show("%s", cmds->str);
g_string_free(cmds, TRUE);
cmds = g_string_new("");
count = 0;
@@ -1589,7 +1589,7 @@ _cmd_list_commands(GList* commands)
curr = g_list_next(curr);
count++;
}
cons_show(cmds->str);
cons_show("%s", cmds->str);
g_string_free(cmds, TRUE);
g_list_free(curr);
@@ -2407,7 +2407,7 @@ cmd_roster(ProfWin* window, const char* const command, gchar** args)
}
return TRUE;
} else {
cons_show(err_msg);
cons_show("%s", err_msg);
return TRUE;
}
@@ -2467,7 +2467,7 @@ cmd_roster(ProfWin* window, const char* const command, gchar** args)
cons_show("Roster contact indent set to: %d", intval);
rosterwin_roster();
} else {
cons_show(err_msg);
cons_show("%s", err_msg);
}
}
} else {
@@ -2501,7 +2501,7 @@ cmd_roster(ProfWin* window, const char* const command, gchar** args)
cons_show("Roster resource indent set to: %d", intval);
rosterwin_roster();
} else {
cons_show(err_msg);
cons_show("%s", err_msg);
}
}
} else if (g_strcmp0(args[1], "join") == 0) {
@@ -2527,7 +2527,7 @@ cmd_roster(ProfWin* window, const char* const command, gchar** args)
cons_show("Roster presence indent set to: %d", intval);
rosterwin_roster();
} else {
cons_show(err_msg);
cons_show("%s", err_msg);
}
}
} else {
@@ -4371,7 +4371,7 @@ cmd_occupants(ProfWin* window, const char* const command, gchar** args)
wins_resize_all();
return TRUE;
} else {
cons_show(err_msg);
cons_show("%s", err_msg);
return TRUE;
}
}
@@ -4391,7 +4391,7 @@ cmd_occupants(ProfWin* window, const char* const command, gchar** args)
occupantswin_occupants_all();
} else {
cons_show(err_msg);
cons_show("%s", err_msg);
}
return TRUE;
}
@@ -4970,8 +4970,8 @@ cmd_sendfile(ProfWin* window, const char* const command, gchar** args)
alt_scheme = OMEMO_AESGCM_URL_SCHEME;
alt_fragment = _add_omemo_stream(&fd, &fh, &err);
if (err != NULL) {
cons_show_error(err);
win_println(window, THEME_ERROR, "-", err);
cons_show_error("%s", err);
win_println(window, THEME_ERROR, "-", "%s", err);
goto out;
}
#endif
@@ -5836,7 +5836,7 @@ cmd_inpblock(ProfWin* window, const char* const command, gchar** args)
prefs_set_inpblock(intval);
inp_nonblocking(FALSE);
} else {
cons_show(err_msg);
cons_show("%s", err_msg);
}
return TRUE;
@@ -6063,7 +6063,7 @@ cmd_statusbar(ProfWin* window, const char* const command, gchar** args)
ui_resize();
return TRUE;
} else {
cons_show(err_msg);
cons_show("%s", err_msg);
cons_bad_cmd_usage(command);
return TRUE;
}
@@ -6094,7 +6094,7 @@ cmd_statusbar(ProfWin* window, const char* const command, gchar** args)
ui_resize();
return TRUE;
} else {
cons_show(err_msg);
cons_show("%s", err_msg);
cons_bad_cmd_usage(command);
return TRUE;
}
@@ -6254,7 +6254,7 @@ cmd_log(ProfWin* window, const char* const command, gchar** args)
prefs_set_max_log_size(intval);
cons_show("Log maximum size set to %d bytes", intval);
} else {
cons_show(err_msg);
cons_show("%s", err_msg);
}
return TRUE;
}
@@ -6304,7 +6304,7 @@ cmd_reconnect(ProfWin* window, const char* const command, gchar** args)
cons_show("Reconnect interval set to %d seconds.", intval);
}
} else {
cons_show(err_msg);
cons_show("%s", err_msg);
cons_bad_cmd_usage(command);
}
@@ -6330,7 +6330,7 @@ cmd_autoping(ProfWin* window, const char* const command, gchar** args)
cons_show("Autoping interval set to %d seconds.", intval);
}
} else {
cons_show(err_msg);
cons_show("%s", err_msg);
cons_bad_cmd_usage(command);
}
@@ -6346,7 +6346,7 @@ cmd_autoping(ProfWin* window, const char* const command, gchar** args)
cons_show("Autoping timeout set to %d seconds.", intval);
}
} else {
cons_show(err_msg);
cons_show("%s", err_msg);
cons_bad_cmd_usage(command);
}
@@ -6416,7 +6416,7 @@ cmd_autoaway(ProfWin* window, const char* const command, gchar** args)
cons_show("Auto away time set to: %d minutes.", minutesval);
}
} else {
cons_show(err_msg);
cons_show("%s", err_msg);
}
return TRUE;
@@ -6439,7 +6439,7 @@ cmd_autoaway(ProfWin* window, const char* const command, gchar** args)
}
}
} else {
cons_show(err_msg);
cons_show("%s", err_msg);
}
return TRUE;
@@ -6506,7 +6506,7 @@ cmd_priority(ProfWin* window, const char* const command, gchar** args)
cl_ev_presence_send(last_presence, 0);
cons_show("Priority set to %d.", intval);
} else {
cons_show(err_msg);
cons_show("%s", err_msg);
}
return TRUE;
@@ -6576,7 +6576,7 @@ cmd_tray(ProfWin* window, const char* const command, gchar** args)
tray_set_timer(intval);
}
} else {
cons_show(err_msg);
cons_show("%s", err_msg);
}
return TRUE;
@@ -7181,22 +7181,21 @@ cmd_pgp(ProfWin* window, const char* const command, gchar** args)
}
cons_show("PGP keys:");
GList* keylist = g_hash_table_get_keys(keys);
GList* curr = keylist;
while (curr) {
ProfPGPKey* key = g_hash_table_lookup(keys, curr->data);
cons_show(" %s", key->name);
cons_show(" ID : %s", key->id);
auto_char char* format_fp = p_gpg_format_fp_str(key->fp);
GHashTableIter iter;
gpointer key, value;
g_hash_table_iter_init(&iter, keys);
while (g_hash_table_iter_next(&iter, &key, &value)) {
ProfPGPKey* pgp_key = (ProfPGPKey*)value;
cons_show(" %s", pgp_key->name);
cons_show(" ID : %s", pgp_key->id);
auto_char char* format_fp = p_gpg_format_fp_str(pgp_key->fp);
cons_show(" Fingerprint : %s", format_fp);
if (key->secret) {
if (pgp_key->secret) {
cons_show(" Type : PUBLIC, PRIVATE");
} else {
cons_show(" Type : PUBLIC");
}
curr = g_list_next(curr);
}
g_list_free(keylist);
p_gpg_free_keys(keys);
return TRUE;
}
@@ -7237,25 +7236,24 @@ cmd_pgp(ProfWin* window, const char* const command, gchar** args)
return TRUE;
}
GHashTable* pubkeys = p_gpg_pubkeys();
GList* jids = g_hash_table_get_keys(pubkeys);
if (!jids) {
if (!pubkeys || g_hash_table_size(pubkeys) == 0) {
cons_show("No contacts found with PGP public keys assigned.");
return TRUE;
}
cons_show("Assigned PGP public keys:");
GList* curr = jids;
while (curr) {
char* jid = curr->data;
ProfPGPPubKeyId* pubkeyid = g_hash_table_lookup(pubkeys, jid);
GHashTableIter iter;
gpointer key, value;
g_hash_table_iter_init(&iter, pubkeys);
while (g_hash_table_iter_next(&iter, &key, &value)) {
char* jid = (char*)key;
ProfPGPPubKeyId* pubkeyid = (ProfPGPPubKeyId*)value;
if (pubkeyid->received) {
cons_show(" %s: %s (received)", jid, pubkeyid->id);
} else {
cons_show(" %s: %s (stored)", jid, pubkeyid->id);
}
curr = g_list_next(curr);
}
g_list_free(jids);
return TRUE;
}
@@ -7468,22 +7466,21 @@ cmd_ox(ProfWin* window, const char* const command, gchar** args)
}
cons_show("OpenPGP keys:");
GList* keylist = g_hash_table_get_keys(keys);
GList* curr = keylist;
while (curr) {
ProfPGPKey* key = g_hash_table_lookup(keys, curr->data);
cons_show(" %s", key->name);
cons_show(" ID : %s", key->id);
auto_char char* format_fp = p_gpg_format_fp_str(key->fp);
GHashTableIter iter;
gpointer key, value;
g_hash_table_iter_init(&iter, keys);
while (g_hash_table_iter_next(&iter, &key, &value)) {
ProfPGPKey* pgp_key = (ProfPGPKey*)value;
cons_show(" %s", pgp_key->name);
cons_show(" ID : %s", pgp_key->id);
auto_char char* format_fp = p_gpg_format_fp_str(pgp_key->fp);
cons_show(" Fingerprint : %s", format_fp);
if (key->secret) {
if (pgp_key->secret) {
cons_show(" Type : PUBLIC, PRIVATE");
} else {
cons_show(" Type : PUBLIC");
}
curr = g_list_next(curr);
}
g_list_free(keylist);
p_gpg_free_keys(keys);
return TRUE;
}
@@ -7491,8 +7488,8 @@ cmd_ox(ProfWin* window, const char* const command, gchar** args)
else if (g_strcmp0(args[0], "contacts") == 0) {
GHashTable* keys = ox_gpg_public_keys();
cons_show("OpenPGP keys:");
GList* keylist = g_hash_table_get_keys(keys);
GList* curr = keylist;
GHashTableIter iter;
gpointer key, value;
GSList* roster_list = NULL;
jabber_conn_status_t conn_status = connection_get_status();
@@ -7502,15 +7499,16 @@ cmd_ox(ProfWin* window, const char* const command, gchar** args)
roster_list = roster_get_contacts(ROSTER_ORD_NAME);
}
while (curr) {
ProfPGPKey* key = g_hash_table_lookup(keys, curr->data);
g_hash_table_iter_init(&iter, keys);
while (g_hash_table_iter_next(&iter, &key, &value)) {
ProfPGPKey* pgp_key = (ProfPGPKey*)value;
PContact contact = NULL;
if (roster_list) {
GSList* curr_c = roster_list;
while (!contact && curr_c) {
contact = curr_c->data;
auto_gchar gchar* xmppuri = g_strdup_printf("xmpp:%s", p_contact_barejid(contact));
if (g_strcmp0(key->name, xmppuri)) {
if (g_strcmp0(pgp_key->name, xmppuri)) {
contact = NULL;
}
curr_c = g_slist_next(curr_c);
@@ -7518,11 +7516,10 @@ cmd_ox(ProfWin* window, const char* const command, gchar** args)
}
if (contact) {
cons_show("%s - %s", key->fp, key->name);
cons_show("%s - %s", pgp_key->fp, pgp_key->name);
} else {
cons_show("%s - %s (not in roster)", key->fp, key->name);
cons_show("%s - %s (not in roster)", pgp_key->fp, pgp_key->name);
}
curr = g_list_next(curr);
}
} else if (g_strcmp0(args[0], "start") == 0) {
@@ -9612,7 +9609,7 @@ cmd_register(ProfWin* window, const char* const command, gchar** args)
auto_char char* err_msg = NULL;
gboolean res = strtoi_range(port_str, &port, 1, 65535, &err_msg);
if (!res) {
cons_show(err_msg);
cons_show("%s", err_msg);
cons_show("");
port = 0;
options_destroy(options);
@@ -9682,7 +9679,7 @@ cmd_strophe(ProfWin* window, const char* const command, gchar** args)
prefs_set_string(PREF_STROPHE_VERBOSITY, args[1]);
return TRUE;
} else {
cons_show(err_msg);
cons_show("%s", err_msg);
}
} else if (g_strcmp0(args[0], "sm") == 0) {
if (g_strcmp0(args[1], "no-resend") == 0) {