glib/tests/protocol.c: In function ‘test_error’:
glib/tests/protocol.c:252:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘long unsigned int’
252 | for (i = 0; i < G_N_ELEMENTS (tests); i++)
| ^
glib/tests/pattern.c: In function ‘main’:
glib/tests/pattern.c:218:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘long unsigned int’
218 | for (i = 0; i < G_N_ELEMENTS (compile_tests); i++)
| ^
glib/tests/pattern.c:225:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘long unsigned int’
225 | for (i = 0; i < G_N_ELEMENTS (match_tests); i++)
| ^
glib/tests/pattern.c:232:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘long unsigned int’
232 | for (i = 0; i < G_N_ELEMENTS (equal_tests); i++)
| ^
glib/tests/gvariant.c: In function ‘append_tuple_type_string’:
glib/tests/gvariant.c:206:17: error: comparison of integer expressions of different signedness: ‘gsize’ {aka ‘long unsigned int’} and ‘gint’ {aka ‘int’}
206 | for (i = 0; i < size; i++)
| ^
glib/tests/gvariant.c:210:13: error: comparison of integer expressions of different signedness: ‘gsize’ {aka ‘long unsigned int’} and ‘int’
210 | if (i < size - 1)
| ^
glib/tests/gvariant.c:223:17: error: comparison of integer expressions of different signedness: ‘gsize’ {aka ‘long unsigned int’} and ‘gint’ {aka ‘int’}
223 | for (i = 0; i < size; i++)
| ^
glib/tests/gvariant.c: In function ‘describe_type’:
glib/tests/gvariant.c:386:29: error: comparison of integer expressions of different signedness: ‘gsize’ {aka ‘long unsigned int’} and ‘gint’ {aka ‘int’}
386 | for (i = 0; i < length; i++)
| ^
glib/tests/gvariant.c: In function ‘describe_info’:
glib/tests/gvariant.c:882:23: error: comparison of integer expressions of different signedness: ‘gsize’ {aka ‘long unsigned int’} and ‘gint’ {aka ‘int’}
882 | for (i = 0; i < length; i++)
| ^
glib/tests/gvariant.c: In function ‘check_offsets’:
glib/tests/gvariant.c:962:21: error: comparison of integer expressions of different signedness: ‘gsize’ {aka ‘long unsigned int’} and ‘gint’ {aka ‘int’}
962 | for (i = 0; i < length; i++)
| ^
glib/tests/gvariant.c: In function ‘tree_instance_check_gvariant’:
glib/tests/gvariant.c:2636:44: error: comparison of integer expressions of different signedness: ‘gboolean’ {aka ‘int’} and ‘guint64’ {aka ‘long unsigned int’}
2636 | return g_variant_get_boolean (value) == tree->data.integer;
| ^~
glib/tests/gvariant.c: In function ‘test_varargs’:
glib/tests/gvariant.c:3090:26: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘guint’ {aka ‘unsigned int’}
3090 | g_assert_true (val == i++ || val == 0);
| ^~
glib/tests/once.c: In function ‘test_once_init_multi_threaded’:
glib/tests/once.c:183:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘long unsigned int’
183 | for (i = 0; i < G_N_ELEMENTS (threads); i++)
| ^
glib/tests/once.c:186:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘long unsigned int’
186 | for (i = 0; i < G_N_ELEMENTS (threads); i++)
| ^
glib/tests/markup-escape.c: In function ‘main’:
glib/tests/markup-escape.c:152:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘long unsigned int’
152 | for (i = 0; i < G_N_ELEMENTS (escape_tests); i++)
| ^
../glib.git/glib/tests/markup-escape.c:159:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘long unsigned int’
159 | for (i = 0; i < G_N_ELEMENTS (unichar_tests); i++)
| ^
glib/tests/node.c: In function ‘traversal_test’:
glib/tests/node.c:214:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘long unsigned int’
214 | for (i = 0; i < G_N_ELEMENTS (orders); i++)
| ^
glib/tests/logging.c: In function ‘compare_fields’:
glib/tests/logging.c:403:17: error: comparison of integer expressions of different signedness: ‘int’ and ‘gsize’ {aka ‘long unsigned int’}
403 | for (i = 0; i < n1; i++)
| ^
glib/tests/logging.c:405:21: error: comparison of integer expressions of different signedness: ‘int’ and ‘gsize’ {aka ‘long unsigned int’}
405 | for (j = 0; j < n2; j++)
| ^
glib/tests/logging.c:410:13: error: comparison of integer expressions of different signedness: ‘int’ and ‘gsize’ {aka ‘long unsigned int’}
410 | if (j == n2)
| ^~
glib/tests/hash.c: In function ‘test_hash_misc’:
glib/tests/hash.c:616:43: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘guint’ {aka ‘unsigned int’}
616 | if (values_len != keys_len && keys_len != g_hash_table_size (hash_table))
| ^~
glib/tests/tree.c: In function ‘test_tree_traverse’:
glib/tests/tree.c:394:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘long unsigned int’
394 | for (i = 0; i < G_N_ELEMENTS (orders); i++)
| ^
This changes it so when a segment is encoded it will be
normalized at parse time which ensures its valid and
it can more easily be compared with other uris.
It’s technically undefined behaviour in C to copy between two
potentially-overlapping regions of memory (just like it is when calling
`memcpy()`). This can easily happen with union members; and the ones in
`GScanner` in particular.
Fix that by copying through an intermediate variable.
Coverity CID: #1427317, 1427340
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
This test asserts that g_file_set_contents_full() will fail when used
on a read-only file, but processes with CAP_DAC_OVERRIDE on Linux or
uid 0 on traditional Unix can and do ignore DAC permissions.
See also #2027, #2028.
Bug-Debian: https://bugs.debian.org/973271
Signed-off-by: Simon McVittie <smcv@collabora.com>
If there is a file descriptor source that has a lower priority
than the one for sources that are going to be dispatched,
all subsequent file descriptor sources (internally sorted by
file descriptor identifier) do not get an update in their GPollRec
and later on wrong sources can be dispatched.
Fix this by first finding the first GPollRec that matches the current
GPollFD, instead of relying on it to be the current one. At
the same time, document the assumptions about the ordering of the
file descriptor records and array and make explicit in the documentation
that the array needs to be passed to g_main_context_check() as it was
received from g_main_context_query().
Added a new test that reproduces the bug by creating two file
descriptor sources and an idle one. Since the first
file descriptor created has a lower identifier and a low priority,
the second one is not dispatched even when it has the same, higher,
priority as the idle source. After fixing this bug, both
higher priority sources are dispatched as expected.
While this patch was written independently, a similar fix for this
bug was first submitted by Eugene M in GNOME/glib!562. Having a
second fix that basically does the same is a reassurance that we
are in the right here.
Fixes#1592
This allows compilers to check the format placeholders properly. It
fixes compilation on clang, which gives a warning about untrusted
strings being passed on to subsequent functions which require format
placeholders.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Just like gcc, clang has supported `__typeof__` for a long time, so
allow it to be used. This fixes compilation of `gio/gcredentials.c` on
macOS (which uses clang by default).
I don’t know which version clang started supporting `__typeof__` in, so
there’s no version check. One can be added in future if there are
problems.
This fixes commit 5b2bee3f53.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
The addition causes the date to shift
forward into 1st of the next month, because a 0-based offset
is compared to be "more than" the days in the month instead of "more than
or equal to".
This is triggered by corner-cases where transition date is 6 days
off the end of the month and our calculations put it at N+1th day of the
month (where N is the number of days in the month). The subtraction should
be triggered to move the date back a week, putting it 6 days off the end;
for example, October 25 for CET DST transition; but due to incorrect comparison
the date isn't shifted back, we add 31 days to October 1st and end up
at November 1st).
Fixes issue #2215.
This reverts commit 851241f19a.
That commit avoids a performance regression but introduces a behavior regression:
changes to /etc/localtime have no effect for the remaining of the application's
runtime.
With the optimization introduced by the previous commit, we can pass NULL to
g_time_zone_new() repeatedly with no performance drawback, so we no longer have
to workaround this case.
Fixes: #2224
We cache GTimeZone instances to avoid expensive construction when the
same id is requested again.
However, if the NULL id is passed to g_time_zone_new(), we always
construct a new instance for the default/fallback timezone.
With the recent introduction of some heavy calculations[1], repeated
instance construction in such cases has visible performance impact in
nautilus list view and other such GtkTreeView consumers.
To avoid this, cache reference to a constructed default timezone and
use it the next time g_time_zone_new() is called with NULL argument,
as long as the default identifier doesn't change. We already did the
same for the local timezone[2].
Fixes: https://gitlab.gnome.org/GNOME/glib/-/issues/2204
Based on idea proposed by Sebastian Keller <skeller@gnome.org>.
[1] 25d950b61f
[2] 551e83662d
The win32 implementation of `g_getenv()` uses GSlice (from within
GQuark), which results in a deadlock when examining the `G_SLICE`
environment variable.
Fix that by inlining a basic implementation of `g_getenv()` at that call
site.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Fixes: #2225
There are various places glib uses __typeof__ for type safety, but
that's a GNUC extension. C++11 has standard decltype() that does a
similar job, at least for cases we care about.
This avoids C++ code to always have to cast return value of
g_object_ref() which was causing type kind of error:
error: invalid conversion from ‘gpointer’ {aka ‘void*’} to
‘GstElementFactory*’ {aka ‘_GstElementFactory*’} [-fpermissive]
g_has_typeof macro is wrongly in the public g_ namespace, internaly
symbols are usually in the glib_ namespace. This will also allow to
define glib_typeof differently on non-GNUC compilers (e.g. c++11
decltype).
glib/gtestutils.h:134:96: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘GFileError’
134 | if (!err || (err)->domain != dom || (err)->code != c) \
| ^~
glib/tests/fileutils.c:1072:15: note: in expansion of macro ‘g_assert_error’
1072 | g_assert_error (error, G_FILE_ERROR, tests[i].expected_error);
| ^~~~~~~~~~~~~~
glib/tests/array-test.c: In function ‘array_remove_index’:
glib/tests/array-test.c:388:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘guint’ {aka ‘unsigned int’}
388 | for (i = 0; i < garray->len; i++)
| ^
glib/tests/array-test.c: In function ‘array_remove_index_fast’:
glib/tests/array-test.c:425:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘guint’ {aka ‘unsigned int’}
425 | for (i = 0; i < garray->len; i++)
| ^
glib/tests/array-test.c: In function ‘array_remove_range’:
glib/tests/array-test.c:462:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘guint’ {aka ‘unsigned int’}
462 | for (i = 0; i < garray->len; i++)
| ^
glib/tests/array-test.c: In function ‘array_sort’:
glib/tests/array-test.c:604:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘guint’ {aka ‘unsigned int’}
604 | for (i = 0; i < garray->len; i++)
| ^
glib/tests/array-test.c: In function ‘array_sort_with_data’:
glib/tests/array-test.c:636:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘guint’ {aka ‘unsigned int’}
636 | for (i = 0; i < garray->len; i++)
| ^
glib/tests/array-test.c: In function ‘byte_array_sort’:
glib/tests/array-test.c:1876:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘guint’ {aka ‘unsigned int’}
1876 | for (i = 0; i < gbarray->len; i++)
| ^
glib/tests/array-test.c: In function ‘byte_array_sort_with_data’:
glib/tests/array-test.c:1904:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘guint’ {aka ‘unsigned int’}
1904 | for (i = 0; i < gbarray->len; i++)
| ^
These slightly improve the tests but, more importantly, squash a
scan-build warning about assigning to a variable which is never
subsequently used:
```
../../../glib/tests/keyfile.c:1150:3: warning: Value stored to 'value' is never read
value = g_key_file_get_string (keyfile, "a", "key=", &error);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../../glib/tests/keyfile.c:1159:3: warning: Value stored to 'value' is never read
value = g_key_file_get_string (keyfile, "a", "key[", &error);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../../../glib/tests/keyfile.c:1176:3: warning: Value stored to 'value' is never read
value = g_key_file_get_string (keyfile, "a", " key", &error);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3 warnings generated.
```
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
This should silence the following warning:
```
../../../glib/tests/mutex.c:206:5: warning: 1st function call argument is an uninitialized value
g_thread_join (threads[i]);
^~~~~~~~~~~~~~~~~~~~~~~~~~
```
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
This should avoid the warning:
```
../../../glib/tests/mainloop.c:119:3: warning: Value stored to 'id' is never read
id = g_source_attach (source, ctx);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
This introduces no functional changes, but should squash a warning from
`scan-build`:
```
../../../glib/ghash.c:575:3: warning: Value stored to 'small' is never read
small = FALSE;
```
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
GLib uses NULL-terminated string arrays (GStrv) in a number of places, however
these are quite hard to construct in C when the number of elements is not known
in advance. GStrvBuilder wraps GPtrArray to make these easy to create with
type safety and does the memory management for you.
When unref'ing child sources, the lock is already held. But instead of
passing TRUE to g_source_unref_internal it currently passes whether the
lock was already held outside of the current invocation. Just pass TRUE
to fix this possible issue.
It’s landed in kernel 5.9: http://lkml.iu.edu/hypermail/linux/kernel/2008.0/02649.html
Note, this is untested because I currently don’t have kernel 5.9. We can
fix anything up if it breaks once the new syscall is wrapped in glibc.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
This allows programs that want to change how log messages are printed,
such as gnome-terminal (gnome-terminal#42) and Flatpak, to override
the log-writer or the legacy log-handler without having to reimplement
the G_MESSAGES_DEBUG filtering logic.
Signed-off-by: Simon McVittie <smcv@collabora.com>
GLib code normally prints info and debug messages to stdout,
but that interferes with programs that are documented to produce
machine-readable output such as JSON or XML on stdout. In particular,
if such a program uses a GLib-based library, setting G_MESSAGES_DEBUG
will typically result in that library's debug messages going to the
program's stdout and corrupting the machine-readable output.
Unix programs can avoid this by using dup2() to move the original stdout
to another fd, then dup2() again to make the new stdout a copy of stderr,
but it's easier if we provide a way to not write debug messages to
stdout in the first place. Calling
g_log_writer_default_set_use_stderr (TRUE) results in behaviour
resembling Python's logging.basicConfig(), with all diagnostics going
to stderr.
Suggested by Allison Karlitskaya on glib#2087.
Signed-off-by: Simon McVittie <smcv@collabora.com>
The basic API that this commit adds allows in-order iterating over a GTree.
For this the following API were implemented or exported:
1) Returning the first or the last node in the tree,
2) Taking a pointer to a node in the tree and returning the previous or the
next in-order node,
3) Allowing to do a binary search for a particular key value and returning
the pointer to its node,
4) Returning the newly inserted or set node from both insert and replace
functions, so this node is immediately available and does not have to be
looked up,
5) Traversing the tree in-order providing a node pointer to the
caller-provided traversal function.
Most of the above functions were already present in the code, but they
returned the value that is stored at a particular node instead of the
pointer to the node itself.
So most of the code for these new API calls is shared with these existing
ones, just adapted to return the pointer to the node.
Additionally, the so called "lower bound" and "upper bound" operations
were implemented.
The first one returns the first element that is greater than or equal to
the searched key, while the second returns the first element that is
strictly greater than the searched key.
Signed-off-by: Maciej S. Szmigiero <maciej.szmigiero@oracle.com>
* Add a debug assert checking whether we have really removed all nodes in
g_tree_remove_all(),
* Print a "LEFT" and "RIGHT" headers before printing a particular tree
branch in g_tree_node_dump(),
* Make the whole thing actually buildable again in the debug mode by
conditionally providing g_tree_dump() declaration in glib/gtree.h.
Signed-off-by: Maciej S. Szmigiero <maciej.szmigiero@oracle.com>
The return value from `g_utf8_get_char_validated()` is a `gunichar`,
which is unsigned, so comparing it with `> 0` is always going to return
true, even for return values `(gunichar) -1` and `(gunichar) -2`, which
indicate errors.
Handle them more explicitly.
oss-fuzz#26083
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
This is very unlikely to happen, but add error handling to mirror the
other calls to `safe_open()`, and shut Coverity up.
Coverity CID: #1430611
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
If this fails to compile on some particularly bizarre Unix platform,
we can relax these assertions; but our expectation is that gssize is
POSIX ssize_t, and that on Unix, GPid is POSIX pid_t.
Signed-off-by: Simon McVittie <smcv@collabora.com>
This is a step towards glib#1484. We officially require a C99 toolchain,
so we can statically assert that our artisanal hand-crafted integer
types are compatible with the ones we would like to recommend people
use instead.
If there are *still* platforms where <stdint.h> is problematic, these
static assertions can act as an early-warning that future GLib releases
will make a C99-compliant <stdint.h> a hard requirement, in ways that
are less straightforward to avoid (see glib#1484 and glib!1300).
Signed-off-by: Simon McVittie <smcv@collabora.com>
We have been passing a &resolved_identifier address around for multiple
functions to set it. Each function may either:
1. leaving it for the next function to set, if returning early;
2. set it to a duplicate of the passed identifier, if not NULL;
3. get a fallback value and set it, otherwise.
This can be simplified by setting it early to either:
1. a duplicate of the passed identifier, if not NULL;
2. a fallback value, otherwise.
This way we can avoid some unnecessary string duplication and freeing.
Also, on Windows, we avoid calling windows_default_tzname() twice.
But the main motivation for this change is enabling the performance
optimization in the next commit.
When the TZ environment variable is not set, we get the local timezone
identifier by reading specific files.
We are going to need these identifiers earlier, so split this logic into
its own function, in preparation for the next commit.
Based on idea proposed by Sebastian Keller <skeller@gnome.org>.
This is exactly the test case from oss-fuzz which triggers a negative
overflow when constructing dates.
oss-fuzz#22758
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
This bumps the coverage of `parse_host()` and `parse_ip_literal()` up to
100% of lines and branches.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
The previous parsing code could read off the end of a URI if it had an
incorrect %-escaped character in.
Fix that, and more closely implement parsing for the syntax defined in
RFC 6874, which is the amendment to RFC 3986 which specifies zone ID
syntax.
This requires reworking some network-address tests, which were
previously treating zone IDs incorrectly.
oss-fuzz#23816
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Having the goto labels at the bottom of a function makes things a little
more readable. This introduces no functional changes.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
This introduces no functional changes, but makes the memory ownership a
little clearer and reduces the length of the code.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
This introduces no functional changes, but will make future changes to
the code a little cleaner.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
If the old value is destroyed before updating the TLS value in pthreads
(or the Windows equivalent) then there’s a risk of infinite recursion if
`g_private_replace()` is called from within the `GDestroyNotify`.
Avoid that by destroying the old value after doing the TLS update.
Thanks to Matthias Clasen for diagnosing the issue.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Fixes: #2210
Rather than invalidating the cache by comparing `TZ` to the cached
timezone identifier, key entirely off the value of `TZ` (and a cached
copy of it).
This fixes the timezone cache being constantly invalidated if `TZ` is
`NULL` (which will always differ from the identifier of the default
local timezone which is constructed from `g_time_zone_new (NULL)`.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Fixes: #2204
They shouldn’t be used to free a list from part-way through, as that
is confusing and will leave a dangling pointer from the previous list
element.
Spotted by Gary Kramlich in !1653.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Symbols on x86 are prefixed with an underscore
but symbols on x64/ARM/ARM64 are not.
Relevant information concerning the prefixes for the architectures
can be found in the vcpkg project [1,2], where arm and arm64 builds
are part of the CI.
Specifically, _WIN64 is defined on Windows ARM64, so this issue is
only visible when building on ARM32.
[1] 08e74979df/ports/glib/fix-arm-builds.patch
[2] https://github.com/microsoft/vcpkg/pull/6116
glib/tests/date.c:778:17: error: comparison of integer expressions of
different signedness: ‘gint’ {aka ‘int’} and ‘long unsigned int’
778 | for (i = 0; i < G_N_ELEMENTS (check_years); i++)
| ^
glib/tests/collate.c:300:17: error: comparison of integer expressions
of different signedness: ‘gint’ {aka ‘int’} and ‘long unsigned int’
300 | for (i = 0; i < G_N_ELEMENTS (test); i++)
| ^
`uri` is always non-`NULL` by the time the `fail` label is reached, so
drop the `NULL` pointer check. Inline the `fail` code since it’s only
used from two places.
Coverity CID: #1430970
Signed-off-by: Philip Withnall <withnall@endlessm.com>
If one thread pool thread fails to set its scheduler settings, it’s
likely that all the rest of them will fail for the same reason. Avoid
printing duplicate critical warnings in that case.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Fixes: #2191
If the calling code adds more option entries than `G_MAXSIZE` then
there’ll be an integer overflow. This seems vanishingly unlikely (given
that all callers use static option entry lists), but add a precondition
anyway.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Fixes: #2197
Behaviour in that case is implementation-defined and how many bytes were
actually written can't be expressed by the return value anymore.
Instead do a short write of G_MAXSSIZE bytes and let the existing loop
for handling short writes takes care of the remaining length.
glib/gfileutils.c: In function ‘write_to_file’:
glib/gfileutils.c:1176:19: error: comparison of integer expressions of different signedness: ‘gssize’ {aka ‘long int’} and ‘gsize’ {aka ‘long unsigned int’} [-Werror=sign-compare]
1176 | g_assert (s <= length);
| ^~
glib/gmacros.h:939:25: note: in definition of macro ‘G_LIKELY’
939 | #define G_LIKELY(expr) (expr)
| ^~~~
glib/gfileutils.c:1176:7: note: in expansion of macro ‘g_assert’
1176 | g_assert (s <= length);
| ^~~~~~~~
Related to issue #1735 (Get back to a -werror build)
sysprof already shows forks in the waterfall. The
main benefit of adding a mark is that it makes the
thread name show up in the trace, next to the fork.
Otherwise it could possibly overflow on 32-bit machines if `year` is
high enough, although I don’t think that’s possible because of limits
applied on it by callers. This should shut Coverity up though.
The limits applied by callers could be circumvented by calling (say)
`g_date_time_add_years()` multiple times. That’s a bug, but not one I’m
going to fix today.
Coverity CID: #1159479
Signed-off-by: Philip Withnall <withnall@endlessm.com>
This might eliminate some false positives being thrown by Coverity to
do with the return value of `uri_decoder()` and whether it’s allocated
anything.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Make `G_URI_FLAGS_PARSE_RELAXED` available instead, for the
implementations which need to handle user-provided or incorrect URIs.
The default should nudge people towards being compliant with RFC 3986.
This required also adding a new `G_URI_PARAMS_PARSE_RELAXED` flag, as
previously parsing param strings *always* used relaxed mode and there
was no way to control it. Now it defaults to using strict mode, and the
new flag allows for relaxed mode to be enabled if needed.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Fixes: #2149
According to my reading of
https://tools.ietf.org/html/rfc3986#section-4, the only requirement for
a URI to be ‘absolute’ (actually, not a relative reference) is for the
scheme to be specified. A hostname doesn’t have to be specified: see any
of the options in the `hier-part` production in
https://tools.ietf.org/html/rfc3986#appendix-A which don’t include
`authority`.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
This reduces the possibility for overflow, and makes the code a little
more conventional to read.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
`guint8` is the conventional way in modern GLib APIs to represent ‘a byte
which could contain arbitrary binary’. `guchar` is not advised for that
(even though it’s equivalent) because it could be misread as `gchar`.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
This reduces the chance of the caller accidentally double-freeing or
use-after-free-ing something.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Sometimes there are sensitive details in URI query components, so we
should provide the option for hiding them too.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
This brings its naming in line with the ‘generic’ error codes in other
error domains.
This is not an API break since `GUriError` hasn’t been in a release yet.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
RFC 3986, section 3 says:
> The scheme and path components are required, though the path may be
> empty (no characters). When authority is present, the path must
> either be empty or begin with a slash ("/") character. When
> authority is not present, the path cannot begin with two slash
> characters ("//"). These restrictions result in five different ABNF
> rules for a path (Section 3.3), only one of which will match any
> given URI reference.
(See https://tools.ietf.org/html/rfc3986#section-3.)
Given that those conditions are almost always going to be true, and that
typically the number and form of arguments passed to g_uri_join() will
be known at compile time, it would be unnecessarily awkward to add a
`GError` argument to g_uri_join() to detect these situations.
Instead, add precondition checks and document the restrictions.
Developers are responsible for ensuring their paths are in the right
format themselves.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
The test was failing since commit 20ae4b46d ("uri: do not add ipv6
brackets on non-ip host").
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
The g_uri_join_internal() function was making a simplification that
userinfo can be encoded with the same restricted character set as the
user field alone, fix this by allowing the correct character set.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Otherwise, the to_string() encoding will not be reversible. Furthermore,
if no distinction is needed in the first place, g_uri_build() with
userinfo should be used instead.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
g_uri_build_with_user() builds a userinfo, but it shouldn't encode it
itself, but let the user flags declare what's there. Otherwise,
to_string() code paths may encode a second time.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Add encoded flags, similar to what was done in commit 7bee36b4 ("uri:
add G_FLAGS_ENCODED_QUERY").
SoupURI has manual handling of encoded path & fragment, but it can rely
on GUri decoding for the rest.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
GTK ci rightly complains about this when ti builds
GLib as a subproject with -Werror=maybe-uninitialized.
subkey_dynamic_w will be freed without being initialized
when the first goto is taken.
The heuristic is a bit too agressive, as we may have hostname with
%-encoded ':' (as shown in GVfs URI tests).
Add an extra test to check :-decoding as well.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Add a few ipv6 scope parsing corner test cases.
- checking incorrect scoped IPv6 ending with only %25 isn't decoded.
- checking valid scoped IPv6 is passing g_uri_is_valid()
As discussed in
https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1567#note_860499,
for historical reasons, GUri accepts the % preceding the zone-id in the
unescaped form as well.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
g_uri_is_valid() should check the given URI is valid following RFC-3986,
and reject relative references.
Fixes: https://gitlab.gnome.org/GNOME/glib/-/issues/2169
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Just to make it a little more obvious that a thread pool can be
initialised with one thread per logical CPU.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Fixes: #272
Improve formatting, and clarify that the same *type* of test fixture can
be reused, not the same specific instance of a test fixture.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Fixes: #250
It may be defined by the environment (we document that as being allowed)
— if so, individual files should not try to redefine it, as that causes
a preprocessor warning.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Apparently, the function calls added in 11729cdc use Foundation, not
Cocoa. Cocoa is a massive superset of Foundation, and is not available
on iOS.
Patch contributed by Jay Freeman, but without providing an e-mail
address. So the git commit cannot be attributed to him.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Fixes: #1869
Various different BSD systems use a different errno from `E_LOOP` (as
defined by POSIX and used on Linux) to indicate that a file is a symlink
when you try to `open()` it with `O_NOFOLLOW`.
Fix the code which detects this. This is a follow-up to #1302.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
These exercise all the code paths I can manage without adding a load of
machinery to inject faults into `write()`.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #1302
Where applicable. Where the current use of `g_file_set_contents()` seems
the most appropriate, leave that in place.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #1302
This is used when creating the temporary file, or new file from scratch.
I wondered about also allowing the file owner and group to be set, but
that’s not as generally applicable — if your process is operating across
multiple user IDs then it likely has some fairly OS-specific
requirements and will need tighter control of its syscalls anyway.
(Eventually, support for setting the file owner and group atomically
could be added by writing out a file using `O_TMPFILE` so it’s not
addressable, and then linking it into the file system in place of the
old file using something like `renameat2(AT_EMPTY_PATH)` or `linkat()`.
That’s currently not possible without patching the kernel with
https://marc.info/?l=linux-fsdevel&m=152472898003523&w=2, as far as I
know at the moment.)
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Fixes: #1203
This moves `write_to_temp_file()` into `g_file_set_contents_full()` and
coalesces its handling of `do_fsync` with the `rename_file()` call. It
adds support for `G_FILE_SET_CONTENTS_DURABLE` and
`G_FILE_SET_CONTENTS_NONE` — previously only
`G_FILE_SET_CONTENTS_CONSISTENT | G_FILE_SET_CONTENTS_ONLY_EXISTING` was
supported.
In the case that `G_FILE_SET_CONTENTS_CONSISTENT |
G_FILE_SET_CONTENTS_DURABLE` is set, an additional `fsync()` is now done
on the directory after renaming the temporary file.
In the case that `G_FILE_SET_CONTENTS_ONLY_EXISTING` isn’t set, the
`fsync()` after writing the temporary file will always be done (unless
the file system guarantees it never needs to be done).
In the case that only `G_FILE_SET_CONTENTS_DURABLE` is set, the
destination file will be written to directly (using this mode is not
really advised).
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Fixes: #1302
This introduces no functional changes, just makes the code a bit more
modular and reusable.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #1302
This is a new version of the g_file_set_contents() API which will allow
its safety to be controlled by some flags, allowing the user to choose
their preferred tradeoff between safety (`fsync()` calls) and speed.
Currently, the flags do nothing and the new API behaves like the old
API. This will change in the following commits.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #1302
The previous implementation of g_uri_unescape_segment() allowed non-utf8
decoded characters. uri_decoder() allows it too with FLAGS_ENCODED (I
think it's abusing a bit the user-facing flags for some internal
decoding behaviour)
However, it didn't allow \0 in the decoded string. Let's have an extra
check for that, outside of uri_decoder().
Fixes: d83d68d64c
Reported-by: Matthias Clasen <mclasen@redhat.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
`getenv()` doesn't work well on Windows, f.ex., it can't fetch env
vars set with `SetEnvironmentVariable()`. This also means that it
doesn't work at all when targeting UWP since that's the only way to
set env vars in that case.
This adds really basic validation that `GTimeZone` can successfully
parse a ‘slim’ format timezone file.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #2129
Since tzcode95f (1995), TZif files have had a trailing
TZ string, used for timestamps after the last transition.
This string is specified in Internet RFC 8536 section 3.3.
init_zone_from_iana_info has ignored this string, causing it
to mishandle timestamps past the year 2038. With zic's new -b
slim flag, init_zone_from_iana_info would even mishandle current
timestamps. Fix this by parsing the trailing TZ string and adding
its transitions.
Closes#2129
Time zone transition times can range from -167:59:59 through
+167:59:59, according to Internet RFC 8536 section 3.3.1;
this is an extension to POSIX. It is needed for proper
support of TZif version 3 files.
It's not clear to me why this argument was excluded in the first place,
and Dan doesn't remember either. At least for consistency with
unescape_string, add it.
See also:
https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1574#note_867283
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
The illegal character set used to be applied only to the decoded
characters.
Fixes: https://gitlab.gnome.org/GNOME/glib/-/issues/2160
Fixes: d83d68d64c ("guri: new URI parsing and generating functions")
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
g_assert_true(), g_assert_cmpint(), and friends, can return to the
caller if test_nonfatal_assertions is set, but this is normally not the
case. In particular, for the purposes of static analysis, we
specifically don't want to assume that they might return. Clang has an
analyzer_noreturn attribute for this exact purpose, which conveniently
already has a macro in gmacros.h.
Fixes: #1288Fixes: #1200
Creating 1000 threads with the default stack size of 8 MiB will fail on
architectures with a 32-bit address space. Move up the existing THREADS
macro and use that instead, but change its definition to 1000 if
pointers are larger than 32 bits.
Signed-off-by: Harald van Dijk <harald@gigawatt.nl>
A query string may have some '=' characters '%'-encoded that could be
split by g_uri_parse_params() incorrectly. Instead, callers should leave
the query part encoded, and let g_uri_parse_params() do the decoding.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
This is a minor convenience, to avoid caller to do further '+' decoding.
According to the W3C HTML specification, space characters are replaced
by '+': https://url.spec.whatwg.org/#urlencoded-parsing
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
This will allow to further enhance the parsing, without breaking API,
and also makes argument on call side a bit clearer than just TRUE/FALSE.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
This should give a bit more flexibility, without drawbacks.
Many URI encoding accept either '&' or ';' as separators.
Change the documentation to reflect that '&' is probably more
common (http query string).
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
gboolean is secretly actually typedef gint gboolean, so the delim_table
is going to take 1KB of stack all by itself. That’s fine, but it could
be smaller.
This strnpbrk()-like block could do with a comment to make it a bit
clearer what it’s doing.
Suggested-by: Philip Withnall <philip@tecnocode.co.uk>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Use this to replace the much-hated `g_debug()` which told people that
`posix_spawn()` (the fast path) wasn’t being used for various reasons.
If people want to make their process spawning faster now, they’ll have
to use a profiling tool like sysprof to check their program’s
performance. Shocking.
I think I was wrong to put this `g_debug()` in there in the first place
— it hasn’t served its purpose of making people speed up their spawn
paths to use `posix_spawn()`, it’s only cluttered up logs and frustrated
people.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
This allows you to see how long each `GMainContext` iteration and each
`GSource` `check`/`prepare`/`dispatch` takes. It provides more detail
than sysprof’s speedtrack plugin can provide, since it has access to
more internal GLib data.
Use it with `sysprof-cli`, for example:
```
sysprof-cli --use-trace-fd -- my-test-program
```
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Add some internal wrappers around sysprof tracing, so that it can be
used throughout GLib without exposing all the details of sysprof
internally.
This adds an optional dependency on `libsysprof-capture-4`. sysprof
support is disabled without it.
This depends on the GLib dependency of `libsysprof-capture` being
dropped in https://gitlab.gnome.org/GNOME/sysprof/-/merge_requests/30,
which has bumped the soname of `libsysprof-capture` and added subproject
support.
The next few commits will add marks that trace out each `GMainContext`
iteration and each `GSource` `check`/`prepare`/`dispatch` call.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
There is a limited (1 or 2 byte) read off the end of the buffer if its
final or penultimate byte is `%` and it’s not nul-terminated after that.
If the buffer *is* nul-terminated then the first `g_ascii_isxdigit()`
call safely returns `FALSE` and the code moves on.
Fix it by adding an additional check, and some unit tests to catch the
behaviour.
This bug is present in libsoup, which `GUri` is based on, but not
exploitable due to how the external API only exposes nul-terminated
strings. See https://gitlab.gnome.org/GNOME/libsoup/-/merge_requests/126
for the fix there.
oss-fuzz#23815
oss-fuzz#23818
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Modify the existing test function to run each test twice: once
nul-terminated and once with a length specified.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
This introduces no functional changes, but will make it easier to add
more tests in future.
It splits the unescaping tests out so the different types of unescaping
(string, bytes, segment) are tested separately, since they have
different limitations.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Modify the existing test function to run each test twice: once
nul-terminated and once with a length specified.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
It seems that `sig_atomic_t` is not the same width as `int` on FreeBSD,
which is causing CI failures:
```
../glib/gmain.c:5206:3: error: '_GStaticAssertCompileTimeAssertion_73' declared as an array with a negative size
g_atomic_int_set (&any_unix_signal_pending, 0);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../glib/gatomic.h💯5: note: expanded from macro 'g_atomic_int_set'
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```
Fix that by only using `sig_atomic_t` if the code is *not* using atomic
primitives (i.e. in the fallback case). `sig_atomic_t` is only a typedef
around an integer type and is not magic. Its typedef is chosen by the
platform to be async-signal-safe (i.e. read or written in one instruction),
but not necessarily thread-safe.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Add a set of new URI parsing and generating functions, including a new
parsed-URI type GUri. Move all the code from gurifuncs.c into guri.c,
reimplementing some of those functions (and
g_string_append_uri_encoded()) in terms of the new code.
Fixes:
https://gitlab.gnome.org/GNOME/glib/issues/110
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Allocate a working buffer before calling `fork()` to avoid calling
`malloc()` in the async-signal-safe context between `fork()` and
`exec()`, where it’s not safe to use.
In this case, the buffer is used to assemble a wrapper around `argv` so
it can be run under `/bin/sh`.
See `man 7 signal-safety`.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Fixes: #2140
Allocate a working buffer before calling `fork()` to avoid calling
`malloc()` in the async-signal-safe context between `fork()` and
`exec()`, where it’s not safe to use.
In this case, the buffer is used to assemble elements from `PATH` with
the binary from `argv[0]` to try executing them.
See `man 7 signal-safety`.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #2140
Query the environment before calling `fork()` so that it doesn’t have to
be called in the async-signal-safe context between `fork()` and
`exec()`.
See `man 7 signal-safety`.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #2140
They’re not safe to call in an async-signal-safe context on Linux.
`sysconf()` is safe to call on FreeBSD and OpenBSD (at least), so
continue doing that.
This will reduce performance in the (already low performance) fallback
case where `/proc` is inaccessible to a forked process on Linux, while
spawning a subprocess.
See `man 7 signal-safety`.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #2140
Use the error handling infrastructure which already exists for other
failures in the async-signal-safe context.
`g_assert()` is unlikely to have caused problems in practice because it
is only async-signal-unsafe when the assertion condition fails.
See `man 7 signal-safety`.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #2140
While `g_ascii_isdigit()` *is* currently async-signal-safe, it’s going
to be hard to remember to keep it that way if the implementation changes
in future.
It seems more robust to just reimplement it here, given that it’s not
much code.
See `man 7 signal-safety`.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #2140
Use normal `close()` instead, which is guaranteed to be
async-signal-safe.
See `man 7 signal-safety`.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #2140
Functions called between `fork()` and `exec()` have to be
async-signal-safe.
Add a comment to each function which is called in that context, and
`FIXME` comments to the non-async-signal-safe functions which end up
being called as leaves of the call graph.
The following commits will fix those `FIXME`s.
See `man 7 signal-safety`.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #2140
There are two variables which are used to pass state from the Unix
signal handler interrupt function to the rest of `gmain.c`. They are
currently defined as `sig_atomic_t`, which means that they are
guaranteed to be interrupt safe. However, it does not guarantee they are
thread-safe, and GLib attaches its signal handler interrupt function to
a worker thread.
Make them thread-safe using atomics. It’s not possible to use locks, as
pthread mutex functions are not signal-handler-safe. In particular, this
means we have to be careful not to end up using GLib’s fallback atomics
implementation, as that secretly uses a mutex. Better to be unsafe than
have a re-entrant call into `pthread_mutex_lock()` from a nested signal
handler.
This commit solves two problems:
1. Writes to `any_unix_signal_pending` and `unix_signal_pending` could
be delivered out of order to the worker thread which calls
`dispatch_unix_signals()`, resulting in signals not being handled
until the next iteration of that worker thread. This is a
performance problem but not a correctness problem.
2. Setting an element of `unix_signal_pending` from
`g_unix_signal_handler()` and clearing it from
`dispatch_unix_signals_unlocked()` (in the worker thread) could
race, resulting in a signal emission being cleared without being
handled. That’s a correctness problem.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Fixes: #1670