The generated gir file marks the size parameter as "out" by default. This is wrong in the context of a caller allocated buffer with a given size. Explicitly marking the size parameter as (in) fixes the issue.
In practice, this will never happen.
If `getcwd()` returns `ERANGE` whenever the working directory is ≥
`PATH_MAX`, though, the previous implementation of the loop would run
until `max_len == G_MAXULONG`, and would then overflow when adding `1`
to it for a nul terminator in the allocation.
Avoid that problem by always keeping `buffer_len` as a power of two, and
relying on `getcwd()` to write a nul terminator within the buffer space
it’s given. It seems to do this on all platforms we care about, because
the previous version of the code never explicitly wrote a nul terminator
anywhere.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Fixes: #98
Various projects are running tests under valgrind, and they are using
the GLib suppresions to avoid false-positive results.
While this is stored in a well-known path for some years, and easy to
figure out from the GLib prefix, it's better to expose it through a
proper pkgconfig variable so that it's easy to get it from any build
system.
This reverts commit 4cad66580b.
Downgrading the criticals was only temporary. Now we’ve branched for
GLib 2.78, the criticals can be reinstated early this cycle, so people
have the maximum time to fix latent bugs in their code.
Fixes: #2951
We were working around that with a call to chdir("."). Internally chdir()
sets up cmd shell-related environment variables, but only if the current
working directory belongs to a volume with a drive letter. For example,
if the current working directory is on a UNC volume like a network share,
the call to chdir() won't help.
Reference:
https://developercommunity.visualstudio.com/t/UCRT-Crash-in-_wspawne-functions/10262748
Add three classes of test case for which g_utf8_normalize() should
safely return NULL:
- Strings ending with a truncated multibyte character which would
extend past the NUL terminator
- Strings ending with a multibyte character which extends past the
length limit provided by the max_len argument
- Strings containing an invalid multibyte character in any position
_g_utf8_normalize_wc() could read past the end of the provided buffer if
it ends with a truncated multibyte character. If max_len is -1, it can
continue reading until it encounters either a NUL or unreadable
memory. Avoid this with extra bounds checks prior to g_utf8_get_char()
to ensure that it does not read past either max_len or a NUL
terminator.
The ref on the timeout source owned by `SendMessageData` was being
dropped just after attaching the source to the main context, leaving it
unowned in that struct. That meant the only ref on the source was held
by the `GMainContext` it was attached to.
This ref was dropped when returning `G_SOURCE_REMOVE` from
`send_message_with_reply_timeout_cb()`. Before that happens,
`send_message_data_deliver_error()` is called, which normally calls
`send_message_with_reply_cleanup()` and destroys the source.
However, if `send_message_data_deliver_error()` is called when the
message has already been delivered, calling
`send_message_with_reply_cleanup()` will be skipped. This leaves the
source pointer in `SendMessageData` dangling, which will cause problems
when `g_source_destroy()` is subsequently called on it.
I’m not sure if it’s possible in practice for this situation to occur,
but the code certainly does nothing to prevent it, and it’s easy enough
to avoid by keeping a strong ref on the source in `SendMessageData`.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #1264
It already implicitly held a strong ref on its `GTask` values, but
didn’t have a free function set so that they would be automatically
unreffed on removal from the map.
This meant that the functions handling removals from the map,
`on_worker_closed()` (via `cancel_method_on_close()`) and
`send_message_with_reply_cleanup()` had to call unref once more than
they would otherwise.
In `send_message_with_reply_cleanup()`, this behaviour depended on
whether it was called with `remove == TRUE`. If not, it was `(transfer
none)` not `(transfer full)`. This led to bugs in its callers.
For example, this led to a direct leak in `cancel_method_on_close()`, as
it needed to remove tasks from `map_method_serial_to_task`, but called
`send_message_with_reply_cleanup(remove = FALSE)` and erroneously didn’t
call unref an additional time.
Try and simplify it all by setting a `GDestroyNotify` on
`map_method_serial_to_task`’s values, and making the refcount handling
of `send_message_with_reply_cleanup()` not be conditional on its
arguments.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #1264
This is equivalent to the current behaviour, but a little clearer in its
meaning.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #1264
The ownership transfers in this code are a bit complex, so adding some
extra documentation and `g_steal_pointer()` calls should hopefully help
clarify things.
This doesn’t introduce any functional changes, just code documentation.
Another drive-by improvement in the quest for #1264.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #1264
The existing comment in the code was correct that `data` is freed when
the task callback is called, because `data` is also pointed to by the
`user_data` for the task, and that’s freed at the end of the callback.
So the existing code was correct to take a copy of `data->task` before
calling `g_task_return_*()`.
After calling `g_task_return_*()`, the existing code unreffed the task
(which is correct), but then didn’t clear the `data->task` pointer,
leaving `data->task` dangling. That could cause a use-after-free or a
double-unref.
Avoid that risk by explicitly clearing `data->task` before calling
`g_task_return_*()`.
After some testing, it turns out this doesn’t actually fix any bugs, but
it’s still a good robustness improvement.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #1264
Calling g_signal_handlers_block/unblock/disconnect_matched with only G_SIGNAL_MATCH_ID
do not match any handlers and return 0.
Fixes: #2980
Signed-off-by: Przemyslaw Gorszkowski <pgorszkowski@igalia.com>
The use of ‘OR’ in the existing documentation suggests that the matching
is disjunctive, but it’s actually conjunctive. Clarify that in the
documentation and add a test.
Spotted while reviewing
https://gitlab.gnome.org/GNOME/glib/-/merge_requests/3376.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>