There was a time-of-check-to-time-of-use (TOCTTOU) race in the keyring
lock code, where it would check the existence of the lock file using
`access()`, then proceed to call `open(O_CREAT | O_EXCL)` to try and
create the lock file once `access()` showed that it didn’t exist.
The problem is that, because this is happening in a shared directory
(`~/.dbus-keyrings`), another process could quite legitimately create
the lock file in the meantime.
Instead, unconditionally call `open()` and ignore errors from it (which
will be returned if the lock file already exists) until it succeeds (or
the code times out).
This eliminates the TOCTTOU race, and simplifies the timeout behaviour
so there aren’t two loops (check for existence, try to create)
happening. It brings this code in line with what dbus.git does (see
`_dbus_keyring_lock()`).
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Fixes: #1954
When multiple tests were run in parallel, this would race on its access
to `~/.dbus-keyrings` to authenticate with the D-Bus server, since the
keyring directory was not appropriately sandboxed to the unit test.
Use `G_TEST_OPTION_ISOLATE_DIRS` to automatically isolate each unit
test’s directory usage.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Fixes: #1954
Commit 721e385 left one remaining race in the filter test, with a
comment associated with it. Unfortunately, the (seemingly unrelated)
changes in #1841 to `GCancellable` seem to have made this remaining race
a lot more likely to fail on FreeBSD than before.
What’s likely to have happened (although I was unable to reproduce the
failure, due to not having a FreeBSD system; I was only able to
reproduce the problem as a 3/1000 failure on Linux, which is still worth
fixing) is that the atomic write of the `FilterData.serial` to be
expected by the filter function sometimes happened after the filter
function had executed, so the expected message was dropped and didn’t
result in an update to the `FilterData` state.
Rework the test so that instead of setting some expectations (on
`FilterData`) in one thread and then checking them in another thread,
the worker thread just unconditionally returns messages from the filter
function to the main thread, and then the main thread checks whether the
expected one has been filtered.
With this change applied, the `gdbus-connection` test passes 5000 times
in a row for me, on Linux; and doesn’t seem to fail any more on the
FreeBSD CI machines over a few runs. (Previously it failed on 4/5 runs.)
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Fixes: #2092Fixes: #1957
Mention in the documentation that (presumably for performance reasons)
the search results from `g_desktop_app_info_search()` are not filtered
by executable presence or hidden attribute.
Perhaps they should be in future, but for now we should at least
document it.
Spotted by Will Thompson.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
With a trivial file that just includes glib.h:
#include <glib.h>
Compiled with:
gcc -c test.c \
-I /tmp/glib/include/glib-2.0/ \
-I /tmp/glib/lib/x86_64-linux-gnu/glib-2.0/include \
-DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_28 \
-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_28 \
-fmax-errors=1 \
-Werror
We get:
In file included from /tmp/glib/include/glib-2.0/glib/gasyncqueue.h:32,
from /tmp/glib/include/glib-2.0/glib.h:32,
from test.c:1:
/tmp/glib/include/glib-2.0/glib/gthread.h: In function ‘g_rec_mutex_locker_new’:
/tmp/glib/include/glib-2.0/glib/gthread.h:396:3: error: ‘g_rec_mutex_lock’ is deprecated: Not available before 2.32 [-Werror=deprecated-declarations]
396 | g_rec_mutex_lock (rec_mutex);
| ^~~~~~~~~~~~~~~~
/tmp/glib/include/glib-2.0/glib/gthread.h:196:17: note: declared here
196 | void g_rec_mutex_lock (GRecMutex *rec_mutex);
| ^~~~~~~~~~~~~~~~
compilation terminated due to -fmax-errors=1.
The problem is that the code in the static inline functions uses
g_rec_mutex_lock, introduced after 2.28. This code is compiled
regardless of if it's actually used or not.
Suppress the warning by using G_GNUC_BEGIN_IGNORE_DEPRECATIONS /
G_GNUC_END_IGNORE_DEPRECATIONS. There are precedents for doing that,
for example g_main_context_pusher_new in gmain.h.
Tested by building with all variations of GLIB_VERSION_MIN_REQUIRED /
GLIB_VERSION_MAX_ALLOWED:
for i in $(seq 26 2 64); do
gcc -c test.c \
-I/tmp/glib/include/glib-2.0 \
-I/tmp/glib/lib/x86_64-linux-gnu/glib-2.0/include \
-DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_$i \
-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_$i \
-fmax-errors=1 \
-Werror
done
Fixes: #2094
Otherwise the code ends up calling `gettext ("")`, which returns the
current translation’s header. The caller should really have provided a
NULL, parameter string, but the empty string is clear enough.
See
https://gitlab.freedesktop.org/accountsservice/accountsservice/-/merge_requests/56.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
gitlab will drop cmd.exe support with GitLab 13 so I took the opportunity to
add new runners with Windows 2016 and powershell as default.
These runners are tagged with win32-ps instead of win32. The old runners
will be switched off in the coming weeks.
The main difference is that all commands and env expansions use powershell
and Windows 2016 instead of 2012r2.
When g_variant_get_child() is called on a variant which has not been
serialized, it serializes it which includes a call to
g_variant_release_children() and therefore means that any children
previously retrieved from the variant are no longer valid (unless
another reference is held on them) and consequently values borrowed from
those children are no longer safe to access. Add a note to the
g_variant_get_child_value() documentation to explain this.
Alternatively, we could say that after the child is freed, values
borrowed from it are no longer valid. But we already have an
implementation which hasn't changed in years which lets them stay valid
if the variant was serialized before the first
g_variant_get_child_value() call.
Here's a demonstration of the memory error:
static const char *get_first_child (GVariant *v) {
g_autoptr(GVariant) child_v = g_variant_get_child_value (v, 0);
return g_variant_get_string (child_v, NULL);
}
int main(int argc, char **argv) {
g_autoptr(GVariant) v = g_variant_new("(@ss)", g_variant_new_string ("hello"), "world");
const char *child1 = get_first_child (v);
const char *child2;
g_variant_get_child (v, 1, "&s", &child2);
printf ("%s\n", child1); // this is a memory error
return 0;
}
The local change from af0e0cb995 in glib ended upstreamed
as 7359c5fd9f312cddd62146896558d8c9bd2bd4cf in valgrind, with
a few minor adjustments requested from there.
Sync this local modification to what ended up upstreamed, to avoid
any doubt regarding it for future syncs of the whole header.
By default, meson builds glib with -Werror=format=2, which
implies -Werror=format-nonliteral. With these flags, clang errors
out on e.g. the g_message_win32_error function, due to "format
string is not a string literal". This function takes a format
string, and passes the va_list of the arguments onwards to
g_strdup_vprintf, which is annotated with printf attributes.
When passing a string+va_list to another function, GCC doesn't warn
with -Wformat-nonliteral. Clang however does warn, unless the
functions themselves (g_message_win32_error and set_error) are decorated
with similar printf attributes (to force the same checks upon the
caller) - see
https://clang.llvm.org/docs/AttributeReference.html#format
for reference.
Adding these attributes revealed one existing mismatched format string
(fixed in the preceding commit).
The gnulib math code uses __builtin_isnanf and __builtin_isnanl
within the __GNUC__ >= 4 ifdef, and clang doesn't provide those
builtins, only the one without a suffix. Make the meson check
match the code it controls, using the exactly right builtins.
Set REPLACE_ISNAN to 1 if either of the have_isnan* functions failed,
this matches how gnulib's m4 routines does it (in gnulib/m4/isnan.m4).
This fixes the isnan functions in the gnulib math header replacement
work on Clang.
The GIO tests memory-monitor-dbus and memory-monitor-portal use a number
of third party Python modules that may not be present when running the
test case.
Instead of failing due to missing imports, catch the ImportError and
mock a test case that skips. This can't use the usual unittest.skip
logic because the test case class itself uses a 3rd party module.
Closes#2083.
There are two memory monitor tests that use Python's unittest module directly,
but GLib tests should be outputting TAP. Use the embedded TAPTestRunner to
ensure that TAP is output for these tests too.
In cases where performance are critical it can be useful to disable
checks and asserts. GStreamer has those options too, using the same name
and setting them yielding means we can set those options on the main
project (e.g. gst-build) and glib will inherit the same value when built
as subproject.
Many locales have no concept of AM/PM notation, and it’s confusing to
them. It’s an Anglo-centric concept which doesn’t belong in the API at
this level — instead, programs should use more generic format specifiers
which leave the details of how to format a date/time to the locale.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Fixes: #2082
The G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE attribute doesn't have to be
always set. See https://gitlab.gnome.org/GNOME/gvfs/-/merge_requests/68
for more details. In that case, the g_file_query_default_handler function
fails with the "No application is registered as handling this file" error.
Let's fallback to the "standard::fast-content-type" attribute instead to
fix issues when opening such files.
https://gitlab.gnome.org/GNOME/nautilus/-/issues/1425
Meson 0.54.0 added a new method meson.override_dependency() that must be
used to ensure dependency consistency. This patch ensures a project that
depends on glib will never link to a mix of system and subproject
libraries. It would happen in such cases:
The system has glib 2.40 installed, and a project does:
dependency('glib-2.0', version: '>=2.60',
fallback: ['glib', 'glib_dep'])
dependency('gobject-2.0')
The first call will configure glib subproject because the system libglib
is too old, but the 2nd call will return system libgobject.
By overriding 'gobject-2.0' dependency while configuring glib subproject
during the first call, meson knows that on the 2nd call it must return
the subproject dependency instead of system dependency.
This also has the nice side effect that with Meson >0.54.0 an
application depending on glib can declare the fallback without knowing
the dependency variable name: dependency('glib-2.0', fallback: 'glib').
"\t" is not escaped by g_markup_escape_text(), as per its documentation:
"Note that this function doesn't protect whitespace and line endings
from being processed according to the XML rules for normalization of
line endings and attribute values."
The relevant portion of the XML specification
https://www.w3.org/TR/xml/#AVNormalize
"For a character reference, append the referenced character to the
normalized value."
"For a white space character (#x20, #xD, #xA, #x9), append a space
character (#x20) to the normalized value."
So the unescape code in GMarkup does the right thing as can be verified
by the added valid-17.* data files for the markup-parse unit test.
(Note that the valid-13.* data files already tested a plain tab
character in an attribute value, among other white space characters).
Note that the libxml2's xmlSetProp() function escapes "\t" into the
character reference "	".
See https://gitlab.gnome.org/GNOME/glib/-/issues/2080
Update our copy of valgrind.h from the Valgrind 3.15 release tarball,
and then re-apply our downstream change af0e0cb995. No other
changes made.
Signed-off-by: Philip Withnall <withnall@endlessm.com>