We need stronger alignment guarantees for the memory allocations done
through g_rc_box_alloc_full(): while the passed block size may be
aligned, we're not aligning the private data size; this means the
overall allocation may become unaligned, and this could raise issues
when we use the private data size as an offset to access the reference
count.
Fixes: #1581
It’s not possible for g_build_home_dir() to return NULL. The fallback
code here seems to originate from commit 1607e3f1 in 2005 (bug 169348),
where it was added with the explanation “Guard against g_home_dir being
NULL”.
The XDG Base Directory specification doesn’t have anything to say about
what to do when $HOME is unset:
https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
It’s all a bit moot, though, becaause since commit 9cbfb560
(bug 773435), g_{get,build}_home_dir() cannot return NULL. So just drop
the fallback.
See discussion on
https://gitlab.gnome.org/GNOME/glib/merge_requests/505#note_386109.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Otherwise we can have problems calling g_get_home_dir() from within a
g_build_*_dir() function elsewhere in gutils.c:
• There will be a deadlock due to trying to recursively acquire the
g_utils_global lock.
• A stale g_home_dir value may be used if a test harness has called
g_set_user_dirs() in the interim.
Fix that by splitting the code to find/construct the home path out of
g_get_home_dir() into g_build_home_dir(), the same way it’s split for
the other g_get_*() functions. Call g_build_home_dir() from any call
site where the g_utils_global lock is held.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Add a new G_TEST_OPTIONS_ISOLATE_XDG_DIRS option for g_test_init() which
automatically creates a temporary set of XDG directories, and a
temporary home directory, and overrides the g_get_user_data_dir() (etc.)
functions for the duration of the unit test with the temporary values.
This is intended to better isolate unit tests from the user’s actual
data and home directory. It works with g_test_subprocess(), but does not
work with subprocesses spawned manually by the test — each unit test’s
code will need to be amended to correctly set the XDG_* environment
variables in the environment of any spawned subprocess.
“Why not solve that by setting the XDG environment variables for the
whole unit test process tree?” I hear you say. Setting environment
variables is not thread safe and they would need to be re-set for each
unit test, once worker threads have potentially been spawned.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
https://gitlab.gnome.org/GNOME/glib/issues/538
Add a new internal function, g_set_user_dirs(), which will safely
override the values returned by g_get_user_data_dir() and friends, and
the value returned by g_get_home_dir().
This is intended to be used by unit tests, and will be hooked up to them
in a following commit.
This can be called as many times as needed by the current process. It’s
thread-safe. It does not modify the environment, so none of the changes
are propagated to any subsequently spawned subprocesses.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
https://gitlab.gnome.org/GNOME/glib/issues/538
While it is currently OK to read the global variables backing functions
like g_get_user_data_dir() without the g_utils_global lock held (since
such a read is always preceeded by a critical section where the variable
is set to its final value), upcoming changes will allow those variables
to be changed. If they are changed from one thread while another thread
is calling (for example) g_get_user_data_dir(), the final read from the
second thread could race with the first thread.
Avoid that by only reading the global variables with the lock held.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
https://gitlab.gnome.org/GNOME/glib/issues/538
While this might seem like a regression, it means that the home
directory can be overridden by GLib internal code, which will be done in
an upcoming commit. This brings g_get_home_dir() inline with functions
like g_get_user_data_dir().
Signed-off-by: Philip Withnall <withnall@endlessm.com>
https://gitlab.gnome.org/GNOME/glib/issues/538
In order to make some guarantees in an upcoming commit that test path
components won’t clash with file system names used by GLib, add a
restriction that test path components cannot start with a dot.
This is an API break, but one which anyone is unlikely to have hit. If
it is an issue, we can relax the restriction to be a warning.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
https://gitlab.gnome.org/GNOME/glib/issues/538
Seems a bit odd to have the documentation comment miles from what it’s
actually documenting.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
https://gitlab.gnome.org/GNOME/glib/issues/538
Split out the code which calculates each XDG variable value from the
code which caches it, so that GLib can internally recalculate the
variables if needed, without necessarily trashing the user-visible
cache.
This will be useful in a following commit to add support for explicitly
reloading the variables.
This commit necessarily reworks how g_get_user_runtime_dir() is
structured, since it was inexplicably structured differently from (but
equivalently to) the other XDG variable functions.
Future refactoring could easily share a lot more code between these
g_build_*() functions.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
https://gitlab.gnome.org/GNOME/glib/issues/538
This is a utility function which I find myself writing in a number of
places. Mostly in unit tests.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
On non-systemd Gentoo systems the chosen timezone is expressed in
/etc/timezone and /etc/localtime may be a copy of the timezone
file instead of symlink. Add this path to the fallback test to
not regress dates into UTC.
This is along the same lines as g_assert_cmpstr(), but for variants.
Based on a patch by Guillaume Desmottes.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
https://gitlab.gnome.org/GNOME/glib/issues/1191
Use macro name that doesn't conflict with string literal encoding prefix `U`.
```
../glib/tests/fileutils.c(282): warning C4133: 'function': incompatible types - from 'unsigned int [2]' to 'const gchar *'
../glib/tests/fileutils.c(284): warning C4133: 'function': incompatible types - from 'unsigned int [2]' to 'const gchar *'
../glib/tests/fileutils.c(285): warning C4133: 'function': incompatible types - from 'unsigned int [2]' to 'const gchar *'
../glib/tests/fileutils.c(286): warning C4133: 'function': incompatible types - from 'unsigned int [2]' to 'const gchar *'
../glib/tests/fileutils.c(287): warning C4133: 'function': incompatible types - from 'unsigned int [3]' to 'const gchar *'
...
```
When parsing an escaped Unicode character in a text format GVariant
string, such as '\U0001F415', the code uses g_ascii_strtoull(). This,
unexpectedly, accepts minus signs, which can cause an assertion failure
when input like '\u-FF4' is presented for parsing.
Validate that there are no leading sign characters when parsing.
This shouldn’t be considered a security bug, because the GVariant text
format parser should not be used on untrusted input.
oss-fuzz#11576
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Unlike g_ascii_strtoull(), g_ascii_string_to_unsigned() does not permit
leading signs (`+` or `-`). Document that.
It’s already in the unit tests.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
It’s perverse, but explicitly documented that strtoull() accepts numbers
with a leading minus sign (`-`) and explicitly casts them to signed
output.
g_ascii_strtoull() is documented to do what strtoull() does (but locale
independently), and its behaviour is correct. However, the documentation
could be a lot clearer about this unexpected behaviour.
Add a unit test for it too.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
In date time formatting routine, instead of converting from UTF-8 to
locale charset and then from locale charset to UTF-8, store all
intermediate result in UTF-8.
This solves the issue where user provided UTF-8 format string might be
unrepresentable in the current locale charset.
Fixes issue #1605.
In glibc, LANGUAGE is used as highest priority guess for category value.
Unset it to avoid interference with tests using setlocale and translation.
Issue #1357.
g_environ_getenv(env, "PATH") and g_environ_setenv(env, "PATH", newpath)
did not have the intended effect on Windows due to the environment block
containing "Path=". Make these functions case-insensitive for Windows.
g_main_context_prepare() needs to calculate the timeout to pass to
poll(), expressed in milliseconds as a gint. But since the ready time
for a GSource is represented by gint64 microseconds, it's possible that
it could be more than G_MAXINT * 1000 microseconds in the future, and so
can't be represented as a gint. This conversion to a narrower signed
type is implementation-defined, but there are two possible outcomes:
* the result is >= 0, in which case poll() will time out earlier than we
might hope (with no adverse consequences besides an unwanted wakeup)
* the result is < 0, in which case, if there are no other sources,
poll() will block forever
This is extremely unlikely to happen in practice, but can be avoided by
clamping the gint64 value, which we know to be positive, to G_MAXINT.
Thanks to Tomasz Miąsko for pointing this out on !496.
This is essentially a C version of the reproducer on #1600. It is based
on the existing test_seconds(), which relates to a similar but distinct
overflow.
I've only actually run this on a system with 32-bit ints, it should work
regardless of the width of an int, since the remainder after wrapping
will by construction be less than 1 second.
Previously, the `guint interval` parameter, measured in seconds, was
multiplied by 1000 and stored in another `guint` field. For intervals
greater than (G_MAXUINT / 1000) seconds, this would overflow; the
timeout would fire much sooner than intended.
Since GTimeoutSource already keeps track of whether it was created at
millisecond or second resolution, always store the passed interval
directly. We later convert the interval to microseconds, stored in a
gint64, so can move the `* 1000` to there.
The eagle-eyed reader might notice that there is no obvious guarantee
that the source's expiration time in microseconds won't overflow the
gint64, but I don't think this is a new problem. Previously, the
monotonic time would have to reach (2 ** 63 - 2 ** 32) microseconds for
this overflow to occur; now it would have to reach approximately (2 **
63 - 2 ** 42) microseconds. Both of these are 292.47 millennia to 5
significant figures.
Fixes#1600.