# Gotchas Append-only log of known pitfalls. One entry per pitfall. Format: ``` ## YYYY-MM-DD — ``` Scan this file before finishing any non-trivial task. --- ## 2026-04-30 — `g_strsplit` result must use `g_strfreev` `g_strsplit` (and `g_strdupv`) return a `gchar**` whose elements are individually GLib-allocated. Free with `g_strfreev`, **not** `g_free`. The latter compiles fine and silently leaks the inner strings. The cleanup macro is `auto_gcharv` (declared in `src/common.h`): ```c auto_gcharv gchar** parts = g_strsplit(line, " ", -1); ``` Mixing `g_free` on a `gchar**` is the most common allocator-mismatch bug in this codebase. --- ## 2026-04-30 — `JABBER_CONNECTED` must be queued in unit tests Most XMPP-touching code paths gate on `connection_get_status()`. The unit- test stub returns `mock()`, so every test reaching that gate must: ```c will_return(connection_get_status, JABBER_CONNECTED); // or will_return(connection_get_status, JABBER_DISCONNECTED); ``` Forgetting this aborts cmocka with a "missing mock value" error. If you see that error, it's almost always `connection_get_status` you forgot. --- ## 2026-04-30 — Autocomplete callbacks must be stateless Some older callbacks keep "last match" state in a file-static `_last_*_match` variable. Do not copy that pattern. A clean canonical example is `roster_contact_autocomplete` (`src/xmpp/roster_list.c`) — it delegates straight to `autocomplete_complete` against a roster-owned `Autocomplete` object and keeps no callback-local state. Stateful callbacks misbehave under shift-tab cycling and break when two completers run concurrently in a layered command (e.g. `/foo set bar ` followed by `/foo set baz `). --- ## 2026-04-30 — CWE-134 format-string discipline Never pass user-controlled or arbitrary strings as the format argument to `printf`-family or GLib formatted-print functions. A recent compiler- hardening pass (cf. cproof commit `9ec01fa8c`) audited and tightened these sites; do not regress. Right: ```c cons_show("%s", user_text); ``` Wrong: ```c cons_show(user_text); ``` The compiler does not always warn, especially across helper layers. Enable and respect `-Wformat -Wformat-security` warnings in any build you trust. --- ## 2026-04-30 — Build inside Docker, not on the host Library version drift between a developer host and `Dockerfile.debian` (GLib, OpenSSL, libstrophe in particular) can mask or invent failures. CI is the source of truth; CI builds inside the Debian image. See `build/docker.md`. If you absolutely must build on the host, mirror the package set in `Dockerfile.debian` exactly and pin versions — you will spend more time chasing version drift than the Docker build would have cost. --- ## 2026-04-30 — Beware of "Profanity" vs "cproof" naming The fork-rename is incomplete. Many files, symbols, copyright headers, and config keys still say `Profanity` / `prof_` / `profanity`. These are authoritative as-is; do **not** rename them opportunistically alongside unrelated changes. Rename work, when it happens, will be a dedicated PR. --- ## 2026-04-30 — Encryption disable builds must compile Each encryption stack (`HAVE_OMEMO`, `HAVE_LIBOTR`, `HAVE_LIBGPGME`) can be turned off at `configure` time. New code that calls into these modules must wrap calls in the matching `#ifdef` and provide a graceful fallback in the `#else`. CI does not always test every disable combination — verify locally with at least the off-build for each stack you touched.