Commit Graph

31804 Commits

Author SHA1 Message Date
Philip Withnall
33d9ba2fcc gstring: Fix overflow check when expanding the string
After commit 34b7992fd6 the overflow check
was only done when expanding the string, but we need to do it before
checking whether to expand the string, otherwise that calculation could
overflow and falsely decide that the string is big enough already.

As a concrete example, consider a `GString` which has:
 * `.len = G_MAXSIZE / 2 + 1`
 * `.allocated_len = G_MAXSIZE / 2 + 1`
and `g_string_append()` is called on it with an input string of length
`G_MAXSIZE / 2`.

This results in a call `g_string_maybe_expand (string, G_MAXSIZE / 2)`,
which calculates `string->len + len` as `(G_MAXSIZE / 2 + 1) +
(G_MAXSIZE / 2)` which evaluates to `1` as it overflows. This is not
greater than `string->allocated_len` (which is `G_MAXSIZE / 2 + 1`), so
`g_string_expand()` is *not* called, and `g_string_maybe_expand()`
returns successfully. The caller then assumes that there’s enough space
in the buffer, and happily continues to cause a buffer overflow.

It’s unlikely anyone could hit this in practice because it requires
ludicrously big strings and `GString` allocations, which likely would
have been blocked by other code, but if we’re going to have the overflow
checks in `GString` then they should be effective.

Spotted by code inspection.

Signed-off-by: Philip Withnall <pwithnall@gnome.org>
2025-06-03 11:31:04 +01:00
Philip Withnall
b7ce23703e Merge branch 'improve-gvaluesetboxed-docs' into 'main'
gobject: clarify in documentation that g_value_set_boxed copies

See merge request GNOME/glib!4652
2025-05-30 10:01:13 +00:00
Marco Trevisan
45869df93c Merge branch 'regex-docs' into 'main'
gregex: Clarify docs for end_pos

See merge request GNOME/glib!4645
2025-05-30 11:48:33 +02:00
Pablo Correa Gómez
bf24002428 gobject: clarify in documentation that g_value_set_boxed copies
This comes as a consequence of confusion by two devs[1]. The wording
is copied from g_value_set_string, which is more clear on what the
function is doing with the object it's consuming.

[1] https://gitlab.gnome.org/GNOME/Incubator/papers/-/merge_requests/467#note_2455770
2025-05-29 23:46:19 +02:00
Philip Withnall
2db24eeef0 Merge branch 'fopen-cloexec' into 'main'
gstdio: Add support for the `e` flag (O_CLOEXEC) to g_fopen()

See merge request GNOME/glib!4564
2025-05-29 10:59:56 +00:00
Philip Withnall
b2f0bb9592 tests: Expand PATH for Python tests on Windows
This works around a Meson bug
(https://github.com/mesonbuild/meson/issues/4668).

If we have a Python test which spawns a built native binary, that binary is
listed in the `depends` argument of the `test()`. On Linux, this results in
the directories containing the built libraries which the binary depends on
being added to the `LD_LIBRARY_PATH` of the test invocation. On Windows,
however, Meson currently doesn’t add those directories to `PATH` (which is
the equivalent of `LD_LIBRARY_PATH`), so we have to do it manually.

This takes the same approach as Christoph Reiter did in
gobject-introspection
(13e8c7ff80/tests/meson.build (L2)).

Signed-off-by: Philip Withnall <pwithnall@gnome.org>
2025-05-28 16:10:55 +01:00
Philip Withnall
306abedea5 tests: Add tests for new e modes for g_fopen()
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
2025-05-28 16:10:48 +01:00
Philip Withnall
ac2ecb5a43 tests: Add e flag to fdopen() calls in gsubprocess tests
Unlike the previous commit, there is no `g_fdopen()` wrapper where we
can add cross-platform support for this.

I’m not adding that now just for `O_CLOEXEC` support for these two
calls, so pass the flag locally for now.

If someone wanted to add a `g_fdopen()` wrapper in future, the
`GLIB_FD_CLOEXEC` here could be refactored easily.

Signed-off-by: Philip Withnall <pwithnall@gnome.org>
2025-05-28 14:37:08 +01:00
Philip Withnall
f9a7ac11f5 gstdio: Add support for the e flag (O_CLOEXEC) to g_fopen()
This adds cross-platform support for it: on glibc, musl and BSD’s libc,
the flag is natively supported. On Windows, convert it to the `N` flag,
which similarly indicates that an open file shouldn’t be inherited by
child processes.

This allows us to unconditionally pass `e` to `g_fopen()` so `O_CLOEXEC`
can easily be set on its FDs.

Also do the same for `g_freopen()`, since it shares the same underlying
mode handling code.

Signed-off-by: Philip Withnall <pwithnall@gnome.org>
2025-05-28 14:37:02 +01:00
Philip Withnall
a672b11024 Merge branch 'wip/chergert/fix-3664' into 'main'
girepository: add singleton GIRepository back

Closes #3664

See merge request GNOME/glib!4630
2025-05-28 12:18:47 +00:00
Michael Catanzaro
9f5a4a4c50 Merge branch 'async-queue-tests-threading' into 'main'
tests: Add atomics to asyncqueue test global variables

See merge request GNOME/glib!4650
2025-05-27 14:14:55 -05:00
Philip Withnall
f447dfa3cd Merge branch 'pr-2025-05-24-asyncqueue-doc' into 'main'
GAysncQueue: use transfer full annotations

Closes #3698

See merge request GNOME/glib!4648
2025-05-27 14:21:59 +00:00
Philip Withnall
66e4f48b69 Merge branch 'mr-2025-05-24-assert-insert-sorted' into 'main'
GAsyncQueue: assert non-null data in push_sorted()

See merge request GNOME/glib!4649
2025-05-27 13:14:04 +00:00
Philip Withnall
4c05dae76e tests: Fix line wrapping in a function definition in asyncqueue
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
2025-05-27 13:17:52 +01:00
Philip Withnall
7e225eaeb3 tests: Add atomics to asyncqueue test global variables
While the test is structured so that each member of these arrays is only
ever accessed by one worker thread, there’s currently no barriers to
synchronise the final read (in the main thread) with the final write (in
a worker thread), which could lead to very occasional failures like this
one (https://gitlab.gnome.org/GNOME/glib/-/jobs/5119324):
```
GLib:ERROR:../glib/tests/asyncqueue.c:203:test_async_queue_threads: assertion failed (sums[i] > 0): (0 > 0)
not ok /asyncqueue/threads - GLib:ERROR:../glib/tests/asyncqueue.c:203:test_async_queue_threads: assertion failed (sums[i] > 0): (0 > 0)
```

Signed-off-by: Philip Withnall <pwithnall@gnome.org>
2025-05-27 13:17:45 +01:00
Alicia Boya García
8dc4df894e GAsyncQueue: assert non-null data in push_sorted()
While working on
https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4648
I realized there is no assertion checking the data argument in either
g_async_queue_push_sorted() or g_async_queue_push_sorted_unlocked().

All the other push functions assert that data is not null, and the
argument is even marked as not nullable in g_async_queue_push_sorted(),
so this is clearly an oversight.

This patch adds the assert in the _unlocked() version, so that it
applies to both.

I have consciously separated this change from the other merge request,
since that one only makes documentation changes, whereas adding an
assert is a subtle change in behavior that could potentially show as
a regression in buggy applications.
2025-05-24 16:43:47 +02:00
Alicia Boya García
71dd49bd8a GAysncQueue: use transfer full annotations
Fixes https://gitlab.gnome.org/GNOME/glib/-/issues/3698

This patch marks the data arguments of the push() methods and the return
values of the pop() methods as transfer full.

This patch also marks the return values of the non-timed pop() functions
as non-nullable, as they can only return NULL when assertions fail.

In the process I also found g_async_queue_push_sorted_unlocked() was
missing a non-nullable annotation, so I added it. Given that
g_async_queue_push_sorted() has a non-nullable annotation, it makes no
sense for the unlocked version to lack it.
2025-05-24 16:32:50 +02:00
Christian Hergert
690ba3b7b5 girepository: add singleton GIRepository back
This is needed to avoid situations where you cannot coordinate between
bindings and libraries which also need to interact with introspection
which could affect bindings.

For example, a Python application using libpeas to load plugins, also in
Python.

Fixes: #3664
2025-05-23 13:52:37 -07:00
Philip Withnall
7b996a6ce5 Merge branch 'th/gobj-empty-notify-queue' into 'main'
[th/gobj-empty-notify-queue] gobject: optimize notify-queue handling for a single freeze

See merge request GNOME/glib!4642
2025-05-23 05:44:43 +00:00
Thomas Haller
3ade8a93f3 gobject: clear "destroy_notify" during g_datalist_id_update_atomic()
During g_datalist_id_update_atomic(), we get "data" and "destroy_notify"
pointers.  The callback can then create, update or steal the data. It
steals it by setting the `*data` to NULL. In that case, the
"destroy_notify" has no more significance, because the old data was
stolen (and won't be touched by g_datalist_id_update_atomic()) and the
new data that we return is NULL (which means there is no data at all,
and nothing to destroy).

Still, to be clearer about that, clear the "destroy_notify" to NULL at a
few places, where we steal the data.

Note that there are other g_datalist_id_update_atomic() places that also
steal the data but still don't reset the "destroy_notify". Those places
are about the quark_closure_array (CArray) and quark_weak_notifies
(WeakRefStack). For those keys, we never set any "destroy_notify". We
relay on the fact that we take care of the data explicitly and we never
set it. We also don't double check that it's really set to NULL, when we
rightly expect it to be NULL already.  At those places, it feels wrong
to suddenly reset "destroy_notify" to NULL.
This is different from the places where this patch clears the
"destroy_notify". At those places, we (sometimes) do have a callback set,
and it might be clearer to explicitly clear it.
2025-05-22 21:24:47 +02:00
Thomas Haller
1818d53034 gobject: optimize notify-queue handling for a single freeze
When we set a property, we usually freeze the queue notification and
thaw it at the end. This currently always requires a per-object
allocation. That is needed to track the freeze count and frozen
properties.

But there are cases, where we freeze only a single time and never track
a frozen property. In such cases, we can avoid allocating a separate
GObjectNotifyQueue instance.

Optimize for that case by initially tracking adding a global, immutable
sentinel pointer "notify_queue_empty". Only when requiring a per-object
queue, allocate one.

This can be useful before calling dispose(). While there are probably
dispose functions that still try to set properties on the object (which
is the main reason we freeze the notification), most probably don't. In
this case, we can avoid allocating the memory during g_object_unref().

Another such case is during object construction. If the object has no
construct properties and the user didn't specify any properties during
g_object_new(), we may well freeze the object but never add properties
to it. In that case too, we can get away without ever allocating the
GObjectNotifyQueue.
2025-05-22 21:04:56 +02:00
Philip Withnall
c108dc09b9 Merge branch 'fix-getenv-win32' into 'main'
Rework Windows implementation of g_getenv()

See merge request GNOME/glib!4637
2025-05-22 11:38:49 +00:00
Luca Bacci
51c71ea6d2 tests/environment: Run some subtests in a subprocess 2025-05-22 11:02:53 +02:00
Luca Bacci
92411ba25e Tests: Add more environment tests 2025-05-22 10:51:36 +02:00
Philip Withnall
45339fdc9a Merge branch 'gio_file_vfs_annotations' into 'main'
gio: add annotations on parameters of 'g_file_monitor_emit_event' and of 'g_vfs_get_file_for_path'

See merge request GNOME/glib!4644
2025-05-21 22:52:39 +00:00
Philip Withnall
a47659d186 gregex: Clarify docs for end_pos
Actually say that it returns the byte after the end of the match (just
like `endptr` in `g_strtod()` does, for example). Previously that wasn’t
documented (but was clear from the unit tests).

Brought up in https://discourse.gnome.org/t/g-match-info-fetch-pos-returns-incorrect-end-pos/28998

Signed-off-by: Philip Withnall <pwithnall@gnome.org>
2025-05-21 23:31:50 +01:00
fbrouille
281f30ef41 gio: add 'type filename' annotation for 'g_vfs_get_file_for_path'
Add the 'type filename' annotation on the parameter 'path'.
2025-05-21 16:08:52 +00:00
fbrouille
5a546d452e gio: add nullable annotation for 'g_file_monitor_emit_event'
Add the nullable annotation on the parameter 'other_file'
and fix the description.
2025-05-21 16:08:38 +00:00
Philip Withnall
ed07e34447 Merge branch 'g_regex_quote_to_monospace' into 'main'
GRegex: apply monospace typeface in description

See merge request GNOME/glib!4643
2025-05-21 11:09:32 +00:00
marklkram
24df68b5f2 GRegex: apply monospace typeface in description
The topic GRegex had strings in double quotes that are more readable
in monospace.

See discussion in #2986
2025-05-20 21:29:45 -04:00
Philip Withnall
05193cdd4d Merge branch 'th/gobj-drop-bit-lock' into 'main'
[th/gobj-drop-bit-lock] gobject: drop object_bit_lock() functions

See merge request GNOME/glib!4641
2025-05-20 17:39:33 +00:00
Philip Withnall
7eba311448 2.85.0
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
2.85.0
2025-05-20 18:24:14 +01:00
Thomas Haller
51dd935202 gobject: drop object_bit_lock() functions
These functions are unused. The per-object bitlock OPTIONAL_FLAG_LOCK
was replaced by using GData's lock and g_datalist_id_update_atomic().

Note that object_bit_lock() was originally introduced to replace global
locks for GObject so that all locks were per-object. Now this lock is
also dropped, and we only use the (per-object) GData lock.

When we introduced object_bit_lock(), we also added optional-flags on
32bit (see HAVE_OPTIONAL_FLAGS_IN_GOBJECT). These flags are still
useful, to have also on x86, so we keep them even if the original user
is gone now.
2025-05-20 18:29:08 +02:00
Philip Withnall
9dc2028c32 Merge branch 'th/gobj-toggle-ref-lock' into 'main'
[th/gobj-toggle-ref-lock] drop object bitlock for toggle references

Closes #3693

See merge request GNOME/glib!4624
2025-05-20 16:10:14 +00:00
Philip Withnall
fb0f3820a1 Merge branch 'atomic-gpointer-annotations' into 'main'
Mark pointer as (type gpointer)

See merge request GNOME/glib!4599
2025-05-20 16:05:15 +00:00
Philip Withnall
fc79ee45ec Merge branch 'android_no_faccessat' into 'main'
glocalfile: Disable faccessat()-based query_exists on Android

See merge request GNOME/glib!4620
2025-05-20 15:14:40 +00:00
Thomas Haller
e6a1e78029 gobject: drop OPTIONAL_BIT_LOCK_TOGGLE_REFS lock
It was replaced by the GData lock and g_datalist_id_update_atomic().

Note that we introduced object_bit_lock() to replace global mutexes.
Now, object_bit_lock() is also replaced, by using the GData lock via
g_datalist_id_update_atomic().

This means, all mutex-like locks on the GObject now go through the GData
lock on the GObject's qdata.

For the moment, the object_bit_lock() API is still here and unused. It
will be dropped in a separate commit.
2025-05-20 16:40:49 +02:00
Thomas Haller
588dbc569d gobject: rework g_object_remove_toggle_ref() to use g_datalist_id_update_atomic() 2025-05-20 16:40:49 +02:00
Thomas Haller
f438ef6802 gobject: rework g_object_add_toggle_ref() to use g_datalist_id_update_atomic() 2025-05-20 16:40:49 +02:00
Thomas Haller
2fe2f2f9b7 gobject: rework toggle_refs_check_and_ref() to use g_datalist_id_update_atomic()
This is the first step to drop OPTIONAL_BIT_LOCK_TOGGLE_REFS lock. That
will happen soon after.

Note that toggle_refs_check_and_ref_or_deref() is called from
g_object_ref()/g_object_unref(), when the ref count toggles between 1
and 2 and called frequently. Also consider that most objects have no
toggle references and would rather avoid the overhead.

Note that we expect that the object has no toggle references. So the
fast path only takes a g_datalist_lock() first, updates the ref-count
and checks OBJECT_HAS_TOGGLE_REF(). If we have no toggle reference, we
avoid the call to g_datalist_id_update_atomic() -- which first needs to
search the datalist for the quark_toggle_refs key.

Only if OBJECT_HAS_TOGGLE_REF(), we call g_datalist_id_update_atomic().
At that point, we pass "already_locked" to indicate that we hold the
lock, and avoid the overhead of taking the lock a second time.

In this commit, the fast-path actually gets worse. Because previously we
already had the OBJECT_HAS_TOGGLE_REF() optimization and only needed the
object_bit_lock(). Now we additionally take the g_datalist_lock(). Note
that the object_bit_lock() will go away next, which brings the fast path
back to take only one bit lock. You might think, that the fast-path then
is still worse, because previously we took a distinct lock
object_bit_lock(), while now even more places go through the GData lock.
Which theoretically could allow for higher parallelism, by taking different
locks. However, note that in both cases these are per-object locks. So
it would be very hard to find a usage where previously higher
parallelism was achieved due to that (e.g. a concurrent g_weak_ref_get()
vs toggling the last reference). And that is only the fast-path in
toggle_refs_check_and_ref_or_deref(). At all other places, we soon will
take one lock less.

This also fixes a regression of commit abdb58007a ('gobject: drop
OPTIONAL_BIT_LOCK_NOTIFY lock'). Note the code comment in
toggle_refs_check_and_ref_or_deref() how it relies to hold the same lock
that is also taken while destroying the object. This was no longer the
case since OPTIONAL_BIT_LOCK_NOTIFY lock was replaced by GData lock.
This is fixed by this commit, because again the same lock is taken.

Fixes: abdb58007a ('gobject: drop OPTIONAL_BIT_LOCK_NOTIFY lock')
2025-05-20 16:40:49 +02:00
Thomas Haller
61aa0c3ace gdataset: add "already_locked" argument to g_datalist_id_update_atomic()
This allows the caller to take the lock on the GData first, and perform
some operations.

This is useful under the assumption, that the caller can find cases
where calling g_datalist_id_update_atomic() is unnecessary, but where
they still need to hold the lock to atomically make that decision.

That can avoid performance overhead, if we can avoid calling
g_datalist_id_update_atomic(). That matters for checking the
toggle-notify in g_object_ref()/g_object_unref().

Note that with "already_locked", g_datalist_id_update_atomic() will
still unlock the GData at the end. That is because the API of
g_datalist_id_update_atomic() requires that it might re-allocate the
buffer, and it can do a more efficient unlock in that case, instead of
leaving it to the caller. The usage and purpose of this parameter is
anyway special, so the few callers will be fine with this asymmetry.
It can safe an additional atomic operation to first set the buffer and
then do a separate g_datalist_unlock().
2025-05-20 16:40:47 +02:00
Thomas Haller
d3e0b3620a gdataset: expose g_datalist_lock()/g_datalist_unlock() as private API
g_datalist_id_update_atomic() allows to use GData's internal look and
perform complex operations on the data while holding the lock.

Now, also expose g_datalist_{lock,unlock}() functions as private API.

That will be useful, because g_datalist_id_update_atomic() and GData's
lock is the main synchronization point for GObject. By being able to
take those locks directly, we can perform operations without having to
also look up GData key.
2025-05-20 16:39:45 +02:00
Philip Withnall
25677d10bf Merge branch '3616-action-map-docs' into 'main'
gactionmap: Fix broken link in documentation comment

Closes #3616

See merge request GNOME/glib!4505
2025-05-20 14:35:17 +00:00
Philip Withnall
e15bb80af4 Merge branch 'th/gdataset-fix-zero-key' into 'main'
[th/gdataset-fix-zero-key] fix and cleanup related to using a zero GQuark for keys in GData

See merge request GNOME/glib!4628
2025-05-20 14:17:46 +00:00
Colin Kinloch
06602315c3 glocalfile: Disable faccessat()-based query_exists on Android
The bionic version of faccessat() returns EINVAL when flags are set.

See 35778253a5
2025-05-20 15:00:02 +01:00
Philip Withnall
546bf019f9 Merge branch 'main' into 'main'
gmessages: add `SYSLOG_IDENTIFIER` to structured logs using select functions

Closes #3656

See merge request GNOME/glib!4589
2025-05-20 13:52:54 +00:00
Thomas Haller
8434618129 gdataset: correctly handle NULL string in g_datalist_get_data()
All code that adds an entry to GData calls down to datalist_append().
No caller would never pass a zero key_id. So a GData will never contain
the zero GQuark.

g_datalist_get_data() allows to lookup the keys by string. Looking up
by string, only makes sense if the string is a valid GQuark. And the
NULL string is not a valid GQuark (or, in another interpretation is to
say that the GQuark of NULL is zero). In any case, the GData does not
contain the zero quark and it should never find a NULL string there.

Note however that you can add invalid (non-zero) GQuarks to GData. That
is because we avoid the overhead of checking that the non-zero key_is is
infact a valid GQuark. Thus, if you called

  g_datalist_get_data(&data, NULL)

the check

  if (g_strcmp0 (g_quark_to_string (data_elt->key), key) == 0)

would have found entries where the key is not a valid GQuark.

Fix that. Looking up a NULL string should never finds an entry.

Fixes: f6a9d04796 ('GDataSet: silently accept NULL/0 as keys')
2025-05-20 15:37:36 +02:00
Thomas Haller
88688b1ae5 gdataset/tests: add another test for GData 2025-05-20 15:37:36 +02:00
Thomas Haller
7a1dfea458 gdataset: check for valid key before taking lock
In g_dataset_id_remove_no_notify() and g_dataset_id_get_data(), check
first the argument before taking a lock.

Note that this doesn't matter much for g_dataset_id_get_data(). We could
leave the check as it was or drop it altogether. That is because
g_dataset_id_get_data() calls g_datalist_id_get_data(), which is fine
with a zero key_id. Also, passing a zero key is not something that would
somebody to normally, so the check is not necessary at all. I leave the
check for consistency with g_dataset_id_remove_no_notify() and do the
change for the same reason as there.

However, the check for key matters for g_dataset_id_remove_no_notify().
That function calls g_data_set_internal(), which must not be called with
zero key.

At this point, it seems a code smell to perform the check after taking
the lock. Something you notice every time that you look at it, and while
technically no problem, it is ugly. Hence the change.
2025-05-20 15:37:36 +02:00
Thomas Haller
8a273a7a3e gdataset: add assertions that we never add a zero key
All public API already ensures that this cannot ever happen.

The assertion is only for the reviewer and ease of mind.
2025-05-20 15:37:36 +02:00