Migrate structure allocations from calloc to glibs g_new0 macro to
improve type safety and memory robustness.
* Type Safety: The macro takes the type name directly, ensuring the
allocated size always matches the pointer type.
* Static Analysis: It guarantees a non-NULL return by aborting on
failure, which silences -fanalyzer warnings regarding potential NULL
pointer dereferences.
* Readability: Removes redundant sizeof() calls and is the glib way
Also refactor the function so we pass it the current version
and don't rely on the define inside of it.
This function only allows version format in the style of "x.y.z".
* Less `GString`.
* Don't `g_free()` a `strdup()`'ed string.
* Don't lookup the `console` window X times, but only once.
Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>
* Add new TLS policy `direct` as a replacement for `legacy`.
* Document that `/[command]?` prints the help of a command.
* Add option to get help via `/command help`.
* Fix `my-prof.supp` generation and tests for out-of-source builds.
Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>
* use `gchar` instead of `char`.
* improve situations when strings must be duplicated or can pass ownership.
* encapsulate the X.509 name details into a struct.
* prevent memory leaks if a name detail is contained multiple times.
Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>
Several users have reported segfaults when starting up profanity which
has OMEMO support, but OMEMO is not set up yet.
@StefanKropp has been able to reproduce this and tracked it down to
`_load_identity()` calling `omemo_known_devices_keyfile_save()`.
The latter then calls `save_keyfile()` which calls
`g_key_file_save_to_file()`. This can then fail if one of the first two
strings is NULL and won't set the `error` on return. In its error handling
`save_keyfile()` unconditionally dereferences `error` which leads to the
segfault.
Fix this and also go through the entire codebase and verify that the usage
of `GError` is done correctly.
Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>
When running profanity under Valgrind with slashguard enabled, the
following error could occur:
```
[...]
==4021347== Invalid read of size 1
==4021347== at 0x4851F49: memchr (vg_replace_strmem.c:986)
==4021347== by 0x45CEAD: _inp_slashguard_check (inputwin.c:183)
==4021347== by 0x45CEAD: inp_readline (inputwin.c:225)
==4021347== by 0x431184: prof_run (profanity.c:121)
==4021347== by 0x42C609: main (main.c:176)
==4021347== Address 0xe850883 is 0 bytes after a block of size 3 alloc'd
==4021347== at 0x48477C4: malloc (vg_replace_malloc.c:446)
[...]
```
`memchr()` requires the complete memory that shall be searched to be
accessible. Using `strchr()` could work for shorter strings, but we only
want to search in the first 4 chars.
Instead of somehow working around those limitations, simply search manually
in the first 4 bytes.
Fixes: 3c56b289 ("Add slashguard feature")
Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>
> The returned data is valid until changes to the hash release those keys.
As of the doc of `g_hash_table_get_keys()` [0].
> The returned data is valid until hash_table is modified.
As of the doc of `g_hash_table_get_values()` [1].
Use this property and create the lists when modifying the hashtable.
The `keys` list is most of the time used sorted, so sort it immediately. In
the cases where it was not used sorted, it does not matter.
This started off by looking into whether this can be improved.
`g_hash_table_foreach()` is discouraged to be used and proposes to use
a `GHashTableIter`. Since our lists are not modified very often it does not
really make sense, so I decided to keep using lists, but allocating
those lists statically instead of per invocation.
Instead of using a list, we could maybe use the `GArray` version, but
I am not sure whether it wouldn't be even better to replace the
`GHashTable` all along to store the `windows` instead.
[0] https://docs.gtk.org/glib/type_func.HashTable.get_keys.html
[1] https://docs.gtk.org/glib/type_func.HashTable.get_values.html
Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>
In order to keep the C plugins API stable, we have to revert this part of
the changes done in 16ed7cc187.
Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>
* Add an internal `_notifier_uninit()` function.
* Instead of `#ifdef` inside `notify()`, provide different target-specific
static implementations.
This also introduces `log_error_once()`.
Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>
While trying to get the unit tests working again I stumbled over all those
things that I thought could be better^TM.
Now we also know "TODO: why does this make the test fail?" - because
the unit tests are brittle AF ... and we have to init the subsystems
we use in the test, otherwise the cleanup will fail...
BTW. you can now also only run a single test ... or a pattern or so ...
you'd have to read how `cmocka_set_test_filter()` works exactly.
Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>
* destroy/free/shutdown/close in reverse order of allocation
* more static/auto_Xfree
* less variables/strlen/GString
* properly `\0`-terminate string of testcase
Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>
Instead of adding stuff to `_shutdown()`, we can now register a shutdown
routine from the respective `init()` function of our modules.
This also has the advantage, that we're sure they're called in reverse
order from how the initialization happened.
I didn't simply use `atexit()` because POSIX says that the number of
possible callbacks is limited (min 32) and I was not sure whether
we will maybe extend this number at one point.
Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>
* Fix some linter suggestions.
* Change some defines to `const` vars.
* Free buffer entries in the reverse order they were allocated.
Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>
In the documentation of the `muc_nick` function we can read:
> The nickname is owned by the chat room and should not be modified or freed
We should reflect that in the return type and `strdup` the value for the
plugin API.
Fixes: https://github.com/profanity-im/profanity/issues/2013
When using `/statusbar tabmode actlist` and `/statusbar self user` then we get `[00:23] [user]` and now `[00:23] [1:user]` where `1` is the active tab. The active tab is only displayed with fulljid.
This commit fixes 7d290b04d.
Fix https://github.com/profanity-im/profanity/issues/1980