Compare commits

..

6 Commits

Author SHA1 Message Date
f63bf57872 fix(omemo): guard NULL fingerprint decode and log failures (CWE-476/457)
All checks were successful
CI Code / Check spelling (pull_request) Successful in 17s
CI Code / Check coding style (pull_request) Successful in 31s
CI Code / Code Coverage (pull_request) Successful in 3m17s
CI Code / Linux (debian) (pull_request) Successful in 4m50s
CI Code / Linux (arch) (pull_request) Successful in 6m50s
CI Code / Linux (ubuntu) (pull_request) Successful in 7m5s
Absorbs the still-relevant null-pointer guards from #107 and extends them for consistency across all _omemo_fingerprint_decode() callers:
- _omemo_fingerprint_decode(): return NULL on NULL input instead of dereferencing it via strlen().
- omemo_is_trusted_identity(): bail out (FALSE) when decode fails and zero-init fingerprint_len, instead of passing a NULL buffer / reading an uninitialized length into signal_buffer_append().
- omemo_trust(): bail out when decode fails (previously unchecked; under OOM it would save a bogus 1-byte identity).

Every decode failure is now logged (omemo_is_trusted_identity / omemo_trust / omemo_untrust) instead of failing silently; omemo_trust also surfaces a user-facing error.

The cmd_funcs.c hunks from #107 are dropped: master already has the strtok guard, and its fdopen guard is more complete (it closes the fd).
2026-06-19 09:46:11 +00:00
f16b26bd6d fix(review): address PR #130 review
- proftest: declare the _mkdir_recursive loop index inside the for.
- xmpp/presence: shorten the resource-snapshot comment to one line.
- command/cmd_funcs: report the /vcard remove index error via cons_show_error.
- common: replace g_assert in g_diff_to_gsize with a log_error + return 0
  (moved out of the header into common.c); take get_random_string length as
  size_t instead of asserting non-negative.
- otr: drop the change-narrating comment on the whitespace memmove.

Refs #112
2026-06-19 09:46:11 +00:00
a4e6419faf test: fix -Wsign-compare in proftest _mkdir_recursive loop
The functional-test harness compared a signed loop index against strlen()'s
size_t, which the newly promoted -Wsign-compare turns into a -Werror failure
when the test binaries are built. Make the index size_t.

Refs #112
2026-06-19 09:46:11 +00:00
7eb9668068 build: Pikaur-safe hardening flags, opt-in sanitizers, -Wsign-compare
Re-introduce the build hardening that 5459e78e8 attempted, in a form that
coexists with Arch/Pikaur builds (the conflict that forced its revert in
0722dc9e3).

configure.ac:
- Add -D_FORTIFY_SOURCE=2 only when neither $CFLAGS nor $CPPFLAGS already
  define _FORTIFY_SOURCE (makepkg injects its own) and not under --coverage.
- Route glib/gio CFLAGS through -isystem so their macros don't trip our -W set.
- Add --enable-sanitizers (ASan + UBSan; unsigned-integer-overflow probed,
  skipped on gcc) for a dedicated CI job, off by default.
- Add --enable-hardening to gate -Wnull-dereference (false positives under
  -O2 on some toolchains), off by default.
- Promote -Wsign-compare from -Wno- to an active probed warning.

Also fix the sign-conversion sites that -Wsign-compare/-Wconversion cleanup
surfaced as safe (pointer-diff to gsize via new g_diff_to_gsize helper,
non-negative int casts), and validate the /vcard remove index through
strtoi_range so a negative argument can no longer become a huge unsigned
index.

Refs #112
2026-06-19 09:46:11 +00:00
7404e7092a fix: more issue #112 follow-ups (stanza-id disco gate, account sanitizer)
- xmpp: gate XEP-0359 stanza-id dedup on disco urn:xmpp:sid:0. Before
  honoring <stanza-id by='…'/> for archive_id dedup, check that the entity
  in `by` (or its domain — that's what profanity disco's on connect)
  announces the namespace; fall back to no-dedup when caps are unknown,
  matching the XEP §6 disco-gate (#1).
- accounts: narrow group-name sanitizer to only the characters GKeyFile
  actually forbids in group headers (`[`, `]`, `\n`, `\r`); `=` and `#` are
  valid inside a header and stay (#2).
- functional tests cover both branches of the disco gate — replayed
  stanza-id is flagged as duplicate when sid:0 is announced, and not
  flagged when it isn't.

Refs #112
2026-06-19 09:46:11 +00:00
62361676fe fix: address issue #112 follow-ups (OTR strip, presence UAF, OMEMO load)
- otr: strip the OTR whitespace tag by shifting the full remaining tail
  (including the trailing NUL) instead of tag_length bytes, which duplicated
  the body for messages longer than the tag (#8).
- xmpp: snapshot resource name/status/priority/presence before
  connection_add_available_resource() transfers ownership of the Resource, so
  the later reads can no longer become a use-after-free (#9).
- omemo: propagate _omemo_finalize_identity_load failure on connect — mark the
  context unloaded, log it, surface a cons_show_error, and stop instead of
  silently leaving OMEMO unavailable (#10).

Refs #112
2026-06-19 09:46:11 +00:00

View File

@@ -43,7 +43,7 @@
#include "ai/ai_client.h"
static const int PAD_MIN_HEIGHT = 100;
static const int PAD_DEAD_SPACE_LIMIT = 2000; // reclaim once the pad holds this much dead space (cursor past live buffer); size-independent, so it never fires while scrolling
static const int PAD_THRESHOLD = 12000; // above buffer cap (~9000): reclaims dead pad space, never fires while scrolling
static gboolean _in_redraw = FALSE;
static void
@@ -56,10 +56,9 @@ _win_ensure_pad_capacity(ProfWin* window, WINDOW* win, int lines_needed)
int cur_height = getmaxy(win);
int cur_width = getmaxx(win);
if (lines_needed >= cur_height - 1) {
// redraw to reclaim dead pad space (cursor far past live buffer, e.g. a long
// append-only session); dead space never accrues while scrolling, only here
int dead = window ? getcury(win) - window->layout->buffer->lines : 0;
if (window && dead > PAD_DEAD_SPACE_LIMIT && !_in_redraw) {
// If we are getting too large, trigger a redraw to clean up old lines
// but only if we are not already in a redraw process.
if (window && cur_height >= PAD_THRESHOLD && !_in_redraw) {
win_redraw(window);
} else {
// resize to required lines + some buffer for next messages
@@ -68,20 +67,6 @@ _win_ensure_pad_capacity(ProfWin* window, WINDOW* win, int lines_needed)
}
}
}
// upper-bound estimate of rows a message body occupies (hard newlines + soft-wrap), to reserve pad space before printing so a tall message isn't clipped (a clipped height desyncs the scroll offset)
static int
_win_estimated_lines(WINDOW* win, const char* const message, int indent, int pad_indent)
{
int usable = MAX(1, getmaxx(win) - (indent + pad_indent));
int newlines = 0;
for (const char* p = message; *p; p++) {
if (*p == '\n') {
newlines++;
}
}
return newlines + utf8_display_len(message) / usable + 2;
}
static const char* LOADING_MESSAGE = "Loading older messages…";
static const char* CONS_WIN_TITLE = "CProof. Type /help for help information.";
static const char* XML_WIN_TITLE = "XML Console";
@@ -2016,7 +2001,7 @@ _win_print_internal(ProfWin* window, const char* show_char, int pad_indent, GDat
}
}
_win_ensure_pad_capacity(window, window->layout->win, getcury(window->layout->win) + _win_estimated_lines(window->layout->win, message + offset, indent, pad_indent));
_win_ensure_pad_capacity(window, window->layout->win, getcury(window->layout->win));
if (prefs_get_boolean(PREF_WRAP)) {
_win_print_wrapped(window->layout->win, message + offset, indent, pad_indent);