The current code is unsafe to use from multiple threads at once.
GIOStream functions like this are supposed to be semi-threadsafe. It's
allowed for them to be called on both a reader thread and a writer
thread at the same time. Of course, it's still tricky and dangerous,
because it's only *really* threadsafe if the handshake has finished,
and API users have no plausible way to know that because the API
does not require performing an explicit handshake operation. But that's
a glib-networking problem. We can at least avoid the most obvious
threadsafety issue here in the API layer.
Note that we'll need to implement the new vfunc in glib-networking for
this to actually work.
Fixes#2393
The documentation for `g_bus_watch_name()` implies that the
`GDestroyNotify` for the user data will be called in the current thread
default `GMainContext`. Currently, it could be called in any thread, as
`client_unref()` can be called in any thread.
Fix that by deferring it to an idle source if `client_unref()` finalises
the `Client` object in a different thread.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
These were missing from the test before the previous commit ported from
`GMainLoop` to `GMainContext`.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
It makes combination exit conditions a lot easier than when using
`g_main_loop_quit()` from different callbacks.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
The first sentence incorrectly said that it checked the type of the
value, and then the second sentence explicitly said it was a programmer
error to give a value of the wrong type.
According to the code, the second sentence is correct.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Fixes: #2425
WebKit wants these private key properties to be readable in order to
implement a deserialization function. Currently they are read-only
because at the time GTlsCertificate was originally designed, the plan
was to support PKCS#11-backed private keys: private keys that are stored
on a smartcard, where the private key is completely unreadable. The
design goal was to support both memory-backed and smartcard-backed
private keys with the same GTlsCertificate API, abstracting away the
implementation differences such that code using GTlsCertificate doesn't
need to know the difference.
The original PKCS#11 implementation was never fully baked and at some
point in the past I deleted it all. It has since been replaced with a
new implementation, including a GTlsCertificate:private-key-pkcs11-uri
property, which is readable. So our current API already exposes the
differences between normal private keys and PKCS#11-backed private keys.
The point of making the private-key and private-key-pem properties
write-only was to avoid exposing this difference.
Do we have to make this API function readable? No, because WebKit could
be just as well served if we were to expose serialize and deserialize
functions instead. But WebKit needs to support serializing and
deserializing the non-private portion of GTlsCertificate with older
versions of GLib anyway, so we can do whatever is nicest for GLib. And I
think making this property readable is nicest, since the original design
reason for it to not be readable is now obsolete. The disadvantage to
this approach is that it's now possible for an application to read the
private-key or private-key-pem property, receive NULL, and think "this
certificate must not have a private key," which would be incorrect if
the private-key-pkcs11-uri property is set. That seems like a minor
risk, but it should be documented.
On Unix platforms, wait() and friends yield an integer that encodes
how the process exited. Confusingly, this is usually not the same as
the integer passed to exit() or returned from main(): conceptually it's
an integer encoding of this tagged union:
enum { EXITED, SIGNALLED, ... } tag;
union {
int exit_status; /* if EXITED */
struct {
int terminating_signal;
bool core_dumped;
} terminating_signal; /* if SIGNALLED */
...
} detail;
Meanwhile, on Windows, wait statuses and exit statuses are
interchangeable.
I find that it's clearer what is going on if we are consistent about
referring to the result of wait() as a "wait status", and the value
passed to exit() as an "exit status".
GSubprocess already gets this right: g_subprocess_get_status() returns
the wait status, while g_subprocess_get_exit_status() genuinely returns
the exit status. However, the GSpawn family of APIs has tended to
conflate the two.
Confusingly, g_spawn_check_exit_status() has always checked a wait
status, and it would not be correct to pass an exit status to it; so
let's deprecate it in favour of g_spawn_check_wait_status(), which
does the same thing that g_spawn_check_exit_status() always did.
Code that needs backwards-compatibility with older GLib can use:
#if !GLIB_CHECK_VERSION(2, 69, 0)
#define g_spawn_check_wait_status(x) (g_spawn_check_exit_status (x))
#endif
Signed-off-by: Simon McVittie <smcv@collabora.com>
Confusingly, g_spawn_check_exit_status() takes a wait status, not an
exit status, so passing g_subprocess_get_exit_status() to it is
incorrect (although both encodings happen to use 0 to encode success
and a nonzero value to encode failure, so in practice this probably
had the desired effect).
Signed-off-by: Simon McVittie <smcv@collabora.com>
Following on from the previous commit, some explicit
`g_main_context_wakeup()` calls were missing from the test code which
only uses `GMainContext`.
Add them, and also add some assertions to check that these functions are
being called in the expected thread (as the code comments say).
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
The tests in `gdbus-names.c` use a mixture of `GMainLoop` and iterating
a `GMainContext` directly. Some of the helper functions based around the
`OwnNameData` struct use the `loop` `GMainLoop` even when called from
tests like `watch_with_different_context()` which themselves use
`GMainContext` directly.
Thus, it’s possible for the `GMainLoop` to not be running, while the
test is iterating on `g_main_context_iteration()`. In this case,
`g_main_loop_quit()` is a no-op and will not wake up the `GMainContext`.
This causes the test to livelock in around 1 in 1200 test runs.
Fix this by adding an explicit `g_main_context_wakeup()` call after each
`g_main_loop_quit()` call. A more comprehensive fix would be to port all
the tests in this file to iterating `GMainContext` directly, and drop
all the `GMainLoop` usage, but I don’t have time for that right now.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
If `g_file_monitor_source_dispatch()` drops the last reference to its
`GLocalFileMonitor`, a deadlock will occur, because disposing the
`GLocalFileMonitor` causes synchronous disposal of the
`GFileMonitorSource`, and hence an attempt to re-lock the already-locked
mutex in the `GFileMonitorSource`.
Fix that by dropping the reference to the `GLocalFileMonitor` after
unlocking.
Diagnosed by Ting-Wei Lan. The bug was originally introduced by me in
commit 592a13b483.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Relax the requirement for the test to only be compiled/run under gcc,
since a version of LLVM was released which supports `--add-symbol`.
`objcopy` should be overrideable to be `llvm-objcopy` by using a machine
file as per https://mesonbuild.com/Machine-files.html#binaries.
Suggested and tested by Grigory Vasilyev.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Fixes: #2423
Clarify that the terms ‘GUID’ and ‘UUID’ are used interchangeably in the
context of D-Bus, and that neither of them are an RFC 4122 UUID.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Update several links to allow the remote to use its configured default
branch name, rather than specifying `master` as the default branch name.
This will help avoid breakage if any of these projects rename their
default branch in the future.
Fix a few of the links where they were hitting redirects or had moved.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #2348
Since commit 87e19535fe, the ETag check when writing out a file through
a symlink (following the symlink) has been incorrectly using the ETag
value of the symlink, rather than the target file. This is incorrect
because the ETag should represent the file content, not its metadata or
links to it.
Fix that, and add a unit test.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Fixes: #2417
This adds g_tls_connection_get_protocol_version(),
g_tls_connection_get_ciphersuite_name(), and DTLS variants. This will
allow populating TLS connection information in the WebKit web inspector.
This is WIP because we found it's not quite possibly to implement
correctly with GnuTLS. See glib-networking!151.
This is the result of checking each `Returns:` line in these files. I’ve
only considered nullability and not other (potentially missing or
incorrect) annotations.
Including suggestions by Simon McVittie.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #2227
In a PKCS#11 operation there are multiple types of PINs possibly
needed and these flags add a way to expose them to the user.
This design exactly matches gnutls' gnutls_pin_flag_t API.
This changeset exposes
* `not-valid-before`
* `not-valid-after`
* `subject-name`
* `issuer-name`
on GTlsCertificate provided by the underlying TLS Backend.
In order to make use of these changes,
see the related [glib-networking MR][glib-networking].
This change aims to help populate more of the [`Certificate`][wk-cert]
info in the WebKit Inspector Protocol on Linux.
This changeset stems from work in Microsoft Playwright to [add more info
into its HAR capture][pw] generated from the Inspector Protocol events
and will bring feature parity across WebKit platforms.
[wk-cert]: 8afe31a018/Source/JavaScriptCore/inspector/protocol/Security.json
[pw]: https://github.com/microsoft/playwright/pull/6631
[glib-networking]: https://gitlab.gnome.org/GNOME/glib-networking/-/merge_requests/156
The `GApplication` must be registered before calling
`g_application_mark_busy()`. Document that, and add a guard.
The same is true for `g_application_unmark_busy()`, but the existing
documentation and guard for `busy_count > 0` are enough.
For the reasons given in the new bit of documentation, GDBusProxy should
not be used for connecting to stateless D-Bus services which may be
restarted at any point.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
https://gitlab.gnome.org/GNOME/glib/issues/1036
Include the base URI in the `g_test_bug()` calls instead. This resolves
inconsistencies between the old bug base (bugzilla.gnome.org) and the
new bug base (gitlab.gnome.org). It also has the advantage that the URI
passed to `g_test_bug()` is now clickable in the code editor, rather
than being split across two locations.
See https://gitlab.gnome.org/GNOME/glib/-/merge_requests/275#note_303175
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Since commit ab285899a6 ('gdbusconnection: Document main context
iteration for unsubscript'), we document when the user is guaranteed
that all resources are gone after g_dbus_connection_signal_unsubscribe().
This is not merely an implementation detail, it's something that the
user needs to be able to rely on. It is good that this is documented.
However, libnm does something different ([1]). It registers to several D-Bus
signals without providing a GDestroyNotify. After unsubscription, it schedules
another idle action with lower priority and uses that to know when
cleanup is complete. I think this is a useful alternative and should
also be guaranteed and documented to work.
Also note that this isn't just some implementation detail that currently
happens to work. GDBusConnection tightly integrates with GMainContext and it
works by scheduling idle sources with G_PRIORITY_DEFAULT priority. It needs to
schedule all events with this same priority, otherwise the ordering is not
preserved. At this point, with GDBusConnection working this way, this is no longer
something that can reasonably be any different. It's how GDBusConnection fundamentally
works, and a user must be able to rely on that. As such, this new promise isn't
something that we would want to break in the future.
Thus document it.
[1] a55c10c6cb/src/libnm-client-impl/nm-client.c (L7918)
This fixes a bug where the family flag was ignored in lookup_data_new,
causing the resolver to call getaddrinfo with no hints set when clearly
the family hint should have been set.
gio/tests/unix-streams.c: In function ‘test_write_async_wouldblock’:
gio/tests/unix-streams.c:692:17: error: comparison of integer expressions of different signedness: ‘guint’ {aka ‘unsigned int’} and ‘gint’ {aka ‘int’}
692 | for (i = 0; i < 4 * pipe_capacity; i++)
| ^
gio/tests/unix-streams.c: In function ‘test_writev_async_wouldblock’:
gio/tests/unix-streams.c:780:17: error: comparison of integer expressions of different signedness: ‘guint’ {aka ‘unsigned int’} and ‘gint’ {aka ‘int’}
780 | for (i = 0; i < 4 * pipe_capacity; i++)
| ^
An application that has been shut down is still marked as registered
even if its implementation has been already destroyed.
This may lead to unguarded crashes when calling functions that have
assumptions for being used with registered applications.
So, when an application is registered, mark it as unregistered just
before destroying its implementation and after being shut down, so that
we follow the registration process in reversed order.
Added tests
gio/tests/socket-common.c: In function ‘socket_address_from_string’:
gio/tests/socket-common.c:50:17: error: comparison of integer expressions of different signedness: ‘int’ and ‘long unsigned int’
50 | for (i = 0; i < G_N_ELEMENTS (unix_socket_address_types); i++)
| ^
gio/tests/gnotification-server.c: In function ‘g_notification_server_bus_acquired’:
gio/tests/gnotification-server.c:224:3: error: missing initializer for field ‘padding’ of ‘GDBusInterfaceVTable’ {aka ‘const struct _GDBusInterfaceVTable’}
224 | };
| ^
gio/tests/gdbus-proxy.c: In function ‘strv_equal’:
gio/tests/gdbus-proxy.c:158:32: error: comparison of integer expressions of different signedness: ‘guint’ {aka ‘unsigned int’} and ‘gint’ {aka ‘int’}
158 | res = g_strv_length (strv) == count;
| ^~
gio/gkeyfilesettingsbackend.c: In function ‘convert_path’:
gio/gkeyfilesettingsbackend.c:155:15: warning: comparison of integer
expressions of different signedness: ‘gsize’ {aka ‘long unsigned int’}
and ‘gint’ {aka ‘int’}
155 | if (key_len < kfsb->prefix_len ||
| ^
gio/tests/gsettings.c: In function ‘strv_set_equal’:
gio/tests/gsettings.c:2268:41: error: comparison of integer expressions of different signedness: ‘guint’ {aka ‘unsigned int’} and ‘gint’ {aka ‘int’}
2268 | res = g_strv_length ((gchar**)strv) == count;
| ^~
gio/tests/gdbus-testserver.c:806:1: error: missing initializer for field ‘padding’ of ‘GDBusInterfaceVTable’ {aka ‘const struct _GDBusInterfaceVTable’}
806 | };
| ^
In file included from gio/gio.h:53,
from gio/tests/gdbus-testserver.c:1:
gdbusconnection.h:395:12: note: ‘padding’ declared here
395 | gpointer padding[8];
| ^~~~~~~
gio/tests/gdbus-testserver.c: In function ‘handle_method_call’:
gio/tests/gdbus-testserver.c:334:23: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘gsize’ {aka ‘long unsigned int’}
334 | for (i = 0; i < n_elts; i++)
| ^
gio/tests/gdbus-testserver.c:343:23: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘gsize’ {aka ‘long unsigned int’}
343 | for (i = 0; i < n_elts; i++)
| ^
gio/tests/gdbus-testserver.c:352:23: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘gsize’ {aka ‘long unsigned int’}
352 | for (i = 0; i < n_elts; i++)
| ^
gio/tests/gdbus-testserver.c:361:23: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘gsize’ {aka ‘long unsigned int’}
361 | for (i = 0; i < n_elts; i++)
| ^
gio/tests/gdbus-testserver.c:370:23: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘gsize’ {aka ‘long unsigned int’}
370 | for (i = 0; i < n_elts; i++)
| ^
gio/tests/gdbus-testserver.c:379:23: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘gsize’ {aka ‘long unsigned int’}
379 | for (i = 0; i < n_elts; i++)
| ^
gio/tests/gdbus-testserver.c:388:23: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘gsize’ {aka ‘long unsigned int’}
388 | for (i = 0; i < n_elts; i++)
| ^
gio/tests/gdbus-testserver.c:397:23: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘gsize’ {aka ‘long unsigned int’}
397 | for (i = 0; i < n_elts; i++)
| ^
gio/tests/gdbus-testserver.c:406:23: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘gsize’ {aka ‘long unsigned int’}
406 | for (i = 0; i < n_elts; i++)
| ^
gio/tests/mimeapps.c: In function ‘strv_equal’:
gio/tests/mimeapps.c:31:32: error: comparison of integer expressions of different signedness: ‘guint’ {aka ‘unsigned int’} and ‘gint’ {aka ‘int’}
31 | res = g_strv_length (strv) == count;
| ^~
gio/tests/proxy-test.c: In function ‘do_echo_test’:
gio/tests/proxy-test.c:855:25: error: comparison of integer expressions of different signedness: ‘gssize’ {aka ‘long int’} and ‘gsize’ {aka ‘long unsigned int’}
855 | for (total = 0; total < nwrote; total += nread)
| ^
gio/tests/file.c: In function ‘written_cb’:
gio/tests/file.c:358:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘size_t’ {aka ‘long unsigned int’}
358 | if (data->pos < strlen (data->data))
| ^
gio/tests/gdbus-test-codegen.c: In function ‘check_object_manager’:
gio/tests/gdbus-test-codegen.c:2344:20: error: comparison of integer expressions of different signedness: ‘guint’ {aka ‘unsigned int’} and ‘int’
2344 | if (om_signal_id != -1)
| ^~
gio/tests/testfilemonitor.c: In function ‘check_expected_events’:
gio/tests/testfilemonitor.c:124:39: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘gsize’ {aka ‘long unsigned int’}
124 | for (i = 0, li = 0, l = recorded; i < n_expected && l != NULL;)
| ^
gio/tests/socket.c: In function ‘test_get_available’:
gio/tests/socket.c:1696:53: error: comparison of integer expressions of different signedness: ‘gssize’ {aka ‘long int’} and ‘long unsigned int’
1696 | if (g_socket_get_available_bytes (server) > sizeof (data))
| ^
gio/tests/gdbus-export.c:130:1: error: missing initializer for field ‘properties’ of ‘GDBusInterfaceInfo’ {aka ‘const struct _GDBusInterfaceInfo’}
130 | };
| ^
In file included from gio/gio.h:57,
from gio/tests/gdbus-export.c:21:
gio/gdbusintrospection.h:156:25: note: ‘properties’ declared here
156 | GDBusPropertyInfo **properties;
| ^~~~~~~~~~
...
However, GLib still can’t guarantee to do rate limiting, as the type of
rate limiting which is appropriate depends on what tasks are being run,
and the GTask thread pool is shared between all tasks (of many different
types) in a process space.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Fixes: #2368
gio/tests/actions.c: In function ‘strv_set_equal’:
gio/tests/actions.c:177:41: error: comparison of integer expressions of different signedness: ‘guint’ {aka ‘unsigned int’} and ‘gint’ {aka ‘int’}
177 | res = g_strv_length ((gchar**)strv) == count;
| ^~
gio/tests/actions.c: In function ‘test_parse_detailed’:
gio/tests/actions.c:473:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘long unsigned int’
473 | for (i = 0; i < G_N_ELEMENTS (testcases); i++)
| ^
gio/tests/actions.c: In function ‘test_entries’:
gio/tests/actions.c:375:5: error: missing initializer for field ‘parameter_type’ of ‘GActionEntry’ {aka ‘const struct _GActionEntry’}
375 | { "foo", activate_foo },
| ^
In file included from gio/gio.h:31,
from gio/tests/actions.c:1:
gio/gactionmap.h:63:16: note: ‘parameter_type’ declared here
63 | const gchar *parameter_type;
| ^~~~~~~~~~~~~~
...
gio/tests/gdbus-peer-object-manager.c: In function ‘mock_interface_get_vtable’:
gio/tests/gdbus-peer-object-manager.c:111:3: error: missing initializer for field ‘padding’ of ‘GDBusInterfaceVTable’ {aka ‘struct _GDBusInterfaceVTable’}
111 | };
| ^
gio/tests/network-address.c: In function ‘main’:
gio/tests/network-address.c:1194:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘long unsigned int’
1194 | for (i = 0; i < G_N_ELEMENTS (host_tests); i++)
| ^
gio/tests/network-address.c:1201:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘long unsigned int’
1201 | for (i = 0; i < G_N_ELEMENTS (uri_tests); i++)
| ^
gio/tests/network-address.c:1208:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘long unsigned int’
1208 | for (i = 0; i < G_N_ELEMENTS (address_tests); i++)
| ^
gio/tests/network-address.c:1215:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘long unsigned int’
1215 | for (i = 0; i < G_N_ELEMENTS (address_tests); i++)
| ^
gio/tests/gsubprocess.c: In function ‘test_communicate_async’:
gio/tests/gsubprocess.c:774:3: error: missing initializer for field ‘running’ of ‘TestAsyncCommunicateData’
774 | TestAsyncCommunicateData data = { flags, 0, };
| ^~~~~~~~~~~~~~~~~~~~~~~~
gio/tests/gsubprocess.c: In function ‘test_communicate_utf8_async’:
gio/tests/gsubprocess.c:1025:3: error: missing initializer for field ‘running’ of ‘TestAsyncCommunicateData’
1025 | TestAsyncCommunicateData data = { flags, 0, };
| ^~~~~~~~~~~~~~~~~~~~~~~~
gio/tests/gsubprocess.c: In function ‘test_communicate_utf8_cancelled_async’:
gio/tests/gsubprocess.c:1058:3: error: missing initializer for field ‘running’ of ‘TestAsyncCommunicateData’
1058 | TestAsyncCommunicateData data = { flags, 0, };
| ^~~~~~~~~~~~~~~~~~~~~~~~
gio/tests/gsubprocess.c: In function ‘test_communicate_utf8_async_invalid’:
gio/tests/gsubprocess.c:1202:3: error: missing initializer for field ‘running’ of ‘TestAsyncCommunicateData’
1202 | TestAsyncCommunicateData data = { flags, 0, };
| ^~~~~~~~~~~~~~~~~~~~~~~~
gio/tests/converter-stream.c: In function ‘g_expander_converter_convert’:
gio/tests/converter-stream.c:128:21: error: comparison of integer expressions of different signedness: ‘int’ and ‘gsize’ {aka ‘long unsigned int’}
128 | for (i = 0; i < block_size; i++)
| ^
gio/tests/converter-stream.c: In function ‘g_compressor_converter_convert’:
gio/tests/converter-stream.c:234:23: error: comparison of integer expressions of different signedness: ‘long int’ and ‘gsize’ {aka ‘long unsigned int’}
234 | if (in_end - in < block_size)
| ^
gio/tests/converter-stream.c:244:21: error: comparison of integer expressions of different signedness: ‘int’ and ‘gsize’ {aka ‘long unsigned int’}
244 | for (i = 0; i < block_size; i++)
| ^
gio/tests/converter-stream.c:257:33: error: comparison of integer expressions of different signedness: ‘long int’ and ‘gsize’ {aka ‘long unsigned int’}
257 | if (v == 0 && in_end - in == block_size && (flags & G_CONVERTER_INPUT_AT_END) == 0)
| ^~
gio/tests/converter-stream.c: In function ‘test_expander’:
gio/tests/converter-stream.c:356:17: error: comparison of integer expressions of different signedness: ‘int’ and ‘long unsigned int’
356 | for (i = 0; i < sizeof(unexpanded_data); i++)
| ^
gio/tests/converter-stream.c: In function ‘test_compressor’:
gio/tests/converter-stream.c:445:17: error: comparison of integer expressions of different signedness: ‘int’ and ‘gsize’ {aka ‘long unsigned int’}
445 | for (i = 0; i < expanded_size; i++)
| ^
gio/tests/converter-stream.c:454:16: error: comparison of integer expressions of different signedness: ‘int’ and ‘gsize’ {aka ‘long unsigned int’}
454 | g_assert (i == expanded_size -1);
| ^~
gio/tests/converter-stream.c: In function ‘test_converter_pollable’:
gio/tests/converter-stream.c:1077:17: error: comparison of integer expressions of different signedness: ‘int’ and ‘gsize’ {aka ‘long unsigned int’}
1077 | for (i = 0; i < expanded_size; i++)
| ^
gio/tests/converter-stream.c:1086:16: error: comparison of integer expressions of different signedness: ‘int’ and ‘gsize’ {aka ‘long unsigned int’}
1086 | g_assert (i == expanded_size -1);
| ^~
The code did not handle EOF (0 byte read) correctly. This can e.g. cause
an infinite loop if an incorrect socks proxy is configured.
Add the appropriate checks and return an G_IO_ERROR_CONNECTION_CLOSED
error if EOF is encountered.
gio/tests/converter-stream.c: In function ‘main’:
gio/tests/converter-stream.c:1220:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘long unsigned int’
1220 | for (i = 0; i < G_N_ELEMENTS (compressor_tests); i++)
| ^
gio/tests/converter-stream.c:1223:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘long unsigned int’
1223 | for (i = 0; i < G_N_ELEMENTS (truncation_tests); i++)
| ^
gio/tests/converter-stream.c:1226:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘long unsigned int’
1226 | for (i = 0; i < G_N_ELEMENTS (charset_tests); i++)
| ^
gio/tests/contenttype.c: In function ‘test_tree’:
gio/tests/contenttype.c:337:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘long unsigned int’
337 | for (i = 0; i < G_N_ELEMENTS (tests); i++)
| ^
gio/tests/contexts.c: In function ‘test_context_specific_emit’:
gio/tests/contexts.c:379:21: error: comparison of integer expressions of different signedness: ‘guint’ {aka ‘unsigned int’} and ‘gint32’ {aka ‘int’}
379 | for (i = 0; i < g_test_rand_int_range (1, 5); i++)
| ^
gio/tests/contexts.c:383:55: error: comparison of integer expressions of different signedness: ‘int’ and ‘guint’ {aka ‘unsigned int’}
383 | while (g_atomic_int_get (&observed_values[i]) != n)
| ^~
gio/tests/contexts.c:387:41: error: comparison of integer expressions of different signedness: ‘gint64’ {aka ‘long int’} and ‘guint64’ {aka ‘long unsigned int’}
387 | if (g_get_monotonic_time () > expiry)
| ^
gio/gsettings-tool.c: In function ‘gsettings_list_children’:
gio/gsettings-tool.c:199:30: error: comparison of integer expressions of different signedness: ‘size_t’ {aka ‘long unsigned int’} and ‘gint’ {aka ‘int’}
199 | if (strlen (children[i]) > max)
| ^
gio/gunixsocketaddress.c: In function ‘g_unix_socket_address_to_native’:
gio/gunixsocketaddress.c:217:15: error: comparison of integer expressions of different signedness: ‘gsize’ {aka ‘long unsigned int’} and ‘gssize’ {aka ‘long int’}
217 | if (destlen < socklen)
| ^
If this g_return_val_if_fail() is ever hit, then we leak arguments.
This is not very important because if your code hits
g_return_val_if_fail() you are invoking undefined behavior, a rather
more serious problem, but let's replace it with g_critical() to be
robust.
This includes a small behavior change: it returns 1 rather than 0 in
this error case.
Found by Coverity.
This function can cause significant delays when the mounted volume
is disconnected or just weird. Use IExtractIconW::GetIconLocation()
instead.
Theoretically, this should require COM to be initialized, but in my tests
this code worked just fine without calling CoInitializeEx().
On Windows gio runs a thread to update appinfo at startup.
If someone unloads gio (this happens when a dynamic gio module gets
unloaded by a program that doesn't use gio itself), there doesn't seem
to be a way to detect that until gio is already gone, and as soon as
gio is gone, the thread crashes, since it tries to execute instructions
that are no longer there.
Holding an extra reference to gio DLL fixes this, but it also prevents
gio from being unloaded, and there's no "weak references" for DLLs.
So we just pin gio and acknowledge that it will never be unloaded.
Fixes#2300Fixes#2359
1) Check that schedule_call_in_idle code branch of gdbusnamewatching.c
is working to call vanished handler in the thread which had watched the name
2) Check cancellation of vanished handler if the name is unwatched before
vanished callback is dispatched.
Closes#2011
Signed-off-by: Frederic Martinsons <frederic.martinsons@sigfox.com>
After the recent reworking of this code it was possible for `g_close()`
to be called on `fd == -1`, which is invalid. It would have reported an
error, were errors not ignored. So it was harmless, but still best to
fix.
Simplify the error handling by combining both error labels and checking
the state of `fd` dynamically.
Coverity CID: #1450834
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
The variable `gconstructor_code` (which is what’s defined by
`gconstructor_as_data_h`) is not used at all inside
`glib-compile-schemas`.
This looks like a copy/paste error from the build definition for
`glib-compile-resources` below, which does need it.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
In the 2.68 cycle we’d added 3 new enumerator elements. Due to the
preceding commit, they can now be annotated with
`GLIB_AVAILABLE_ENUMERATOR_IN_2_68`, which will make it a bit easier for
third party projects to notice when they’re using these symbols without
having bumped their GLib dependency.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Fixes: #2327
`""` is not a valid path (`stat()` on it returns `ENOENT`). Previously,
a full `GLocalFile` was being created, which ended up resolving to
`$CWD`, through path canonicalisation. That isn’t right.
Fix it by creating a `GDummyFile` instead, and adding a unit test.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Fixes: #2328
Calling `dlopen()` with `libutil.so` makes the installed tests depend on
having glibc's development files installed. To avoid this, we can work
out the runtime library name at build time and `dlopen` that instead.
This approach is [taken from libfprint][1], thanks to Marco Trevisan.
[1]: f401f399a8
`ENXIO` can be returned from `open(2)` for special files (FIFOs, device
files and domain sockets) which are not backed by anything.
This fixes the error returned by `g_file_replace()` when trying to
replace such a file, so that it now matches the documentation.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
These test all the functionality and combinations of flags I can think
of. They do not cover dynamic behaviour (for example, what would happen
if the source file is deleted by another process part-way through a call
to `g_file_replace()`).
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
The `G_FILE_CREATE_REPLACE_DESTINATION` flag is equivalent to unlinking
the destination file and re-creating it from scratch. That did
previously work, but in the process the code would call `open(O_CREAT)`
on the file. If the file was a dangling symlink, this would create the
destination file (empty). That’s not an intended side-effect, and has
security implications if the symlink is controlled by a lower-privileged
process.
Fix that by not opening the destination file if it’s a symlink, and
adjusting the rest of the code to cope with
- the fact that `fd == -1` is not an error iff `is_symlink` is true,
- and that `original_stat` will contain the `lstat()` results for the
symlink now, rather than the `stat()` results for its target (again,
iff `is_symlink` is true).
This means that the target of the dangling symlink is no longer created,
which was the bug. The symlink itself continues to be replaced (as
before) with the new file — this is the intended behaviour of
`g_file_replace()`.
The behaviour for non-symlink cases, or cases where the symlink was not
dangling, should be unchanged.
Includes a unit test.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Fixes: #2325
Since a following commit is going to add a new test which references
Gitlab, so it’s best to move the URI bases inside the test cases.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
When GLib code is checked out with Windows line endings (happens on Windows),
data-to-c.py embedded that line endings into generated string literal. And
then they translated to double newlines in glib-compile-resources output.
clang-cl failed to compile such files because of empty lines in the middle of
multiline macros:
#define G_MSVC_CTOR(_func,_sym_prefix) \
static void _func(void); \
To fix the issue, enable 'universal newlines' mode when reading the input in
data-to-c.py - translate both '\n' and '\r\n' to '\n'.
Fixes https://gitlab.gnome.org/GNOME/glib/-/issues/2340
This will require distributions to ensure they pass
`--localstatedir=/var` correctly to Meson, but they should be doing that
already.
See https://mesonbuild.com/Builtin-options.html#directories for details
about how Meson treats `localstatedir` differently from most other `dir`
variables.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
It’s unlikely that the machine ID will be invalid (it’s system
configuration), but it would be helpful to not propagate invalid IDs
further, since a lot of things rely on it.
It’s not easy to test this (it requires factoring out the code so it can
be used from a test program, or allowing it to load a machine ID from a
custom path), so I haven’t added unit tests. I’ve tested manually by
overriding the loaded machine ID.
Coverity CID: #1430944
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
For non-Linux UNIX systems, the label 'close_libutil:' in
'test_pollable_unix_pty()' will have no statement that goes with that
label. Just do a 'return' on non-Linux UNIX systems.
File monitor creation may fail. We should check for this, rather than
ignoring it and then spewing criticals upon improperly assuming that we
have a valid GFileMonitor rather than NULL.
In practice, creating the GFileMonitors here fail when opening a large
number of tabs in Epiphany. I'm still investigating to see why, but it
doesn't matter for the purposes of this commit.
Expand an existing unit test to check that the target FD of a
`g_subprocess_launcher_take_fd()` call doesn’t get closed when
`g_subprocess_launcher_close()` is called. Only the source FD should be
closed by the parent process.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #2332
This is a regression introduced in commit 67a589e505. Previously, the
source/target FD pairs were stored in `needdup_fd_assignments`, in
consecutive entries, so source FDs had even indices and target FDs had
odd indices.
I didn’t notice that the array index was being incremented by 2 when
closing FDs, when porting from the old code. So previously the code was
only closing the source FDs; after the port, it was closing source and
target FDs.
That’s incorrect, as the target FDs are just integers in the parent
process. It’s only in the child process where they are actually FDs —
and `g_subprocess_launcher_close()` is never called in the child
process.
This resulted in some strange misbehaviours in any process which used
`g_subprocess_launcher_take_fd()` with target FDs which could have
possibly aliased with other FDs in the parent process (and which weren’t
equal to their mapped source FDs).
Thanks to Olivier Fourdan for the detailed bug report.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Fixes: #2332
This was correctly annotated for proper return values but in case of out
parameters it was only annotated as (optional) and not additionally as
(nullable).
This improves performance by eliminating the use of a
`GSpawnChildSetupFunc` in the common case (since that setup code has now
moved into `g_spawn*()` itself), and enables the use of the fix to avoid
the child error reporting FD being overwritten by target FD mappings,
introduced via `g_spawn_async_with_pipes_and_fds()`.
It reworks how the source/target FD mapping is stored within
`GSubprocessLauncher` to match what `g_spawn*()` uses. The two
approaches are equivalent.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Fixes: #2097
gio/gmemoryoutputstream.c: In function ‘g_memory_output_stream_seek’:
gio/gmemoryoutputstream.c:792:44: error: comparison of integer expressions of different signedness: ‘goffset’ {aka ‘long int’} and ‘gsize’ {aka ‘long unsigned int’}
792 | if (priv->realloc_fn == NULL && absolute > priv->len)
| ^
gio/gdummyfile.c: In function ‘unescape_string’:
gio/gdummyfile.c:485:32: error: comparison of integer expressions of different signedness: ‘long int’ and ‘size_t’ {aka ‘long unsigned int’}
485 | g_warn_if_fail (out - result <= strlen (escaped_string));
| ^~
gio/gapplication-tool.c: In function ‘app_help’:
glib/gmacros.h:806:26: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘size_t’ {aka ‘long unsigned int’}
gio/gapplication-tool.c:121:26: note: in expansion of macro ‘MAX’
121 | maxwidth = MAX(maxwidth, strlen (_(substvars[i].var)));
| ^~~
gio/gapplication-tool.c: In function ‘app_help’:
glib/gmacros.h:806:26: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘size_t’ {aka ‘long unsigned int’}
gio/gapplication-tool.c:140:20: note: in expansion of macro ‘MAX’
140 | maxwidth = MAX(maxwidth, strlen (topics[i].command));
| ^~~
gio/gapplication-tool.c: In function ‘app_help’:
gio/gapplication-tool.c:90:21: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘long unsigned int’
90 | for (i = 0; i < G_N_ELEMENTS (topics); i++)
| ^
gio/gapplication-tool.c:117:25: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘long unsigned int’
117 | for (i = 0; i < G_N_ELEMENTS (substvars); i++)
| ^
gio/gapplication-tool.c:121:25: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘long unsigned int’
121 | for (i = 0; i < G_N_ELEMENTS (substvars); i++)
| ^
gio/gapplication-tool.c:137:21: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘long unsigned int’
137 | for (i = 0; i < G_N_ELEMENTS (topics); i++)
| ^
gio/gapplication-tool.c:140:21: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘long unsigned int’
140 | for (i = 0; i < G_N_ELEMENTS (topics); i++)
| ^
Since the previous commit, the generic `GInputStream` implementation of
`skip()` is now equivalent, and results in the same calls to `lseek()`.
Heavily based on an approach by Dan Winship in
https://bugzilla.gnome.org/show_bug.cgi?id=681374.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #587
The default implementation of `g_input_stream_skip()` can skip off the
end of resizable streams, as that’s the behaviour of `g_seekable_seek()`
for that type of stream.
This has previously been fixed for local file input streams (commit
89f9615835), and a unit test added there.
However, the fix should be more generally made in `GInputStream`.
This commit reworks an old patch by Dan Winship on
https://bugzilla.gnome.org/show_bug.cgi?id=681374, which took that
approach.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Fixes: #587
This is a workaround for the fact that forking without execing is not
easy to do correctly, and `GTestDBus` doesn’t do it correctly. However,
`GTestDBus` is de-facto deprecated and so putting any more effort in is
a waste.
This fixes an issue where a test would print duplicate output when
outputting to a fully-buffered FD, such as a pipe. This is because the
buffer is non-empty before the `fork()`, and ends up duplicated in the
parent and child processes, both of which later flush the duplicated
buffer contents.
Diagnosed and fix suggested by Simon McVittie.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Fixes: #2322
Swedish as spoken in El Salvador is not listed in
/usr/share/i18n/SUPPORTED, and in any case is probably not what we meant.
A more plausible language code would be Swedish as spoken in Sweden.
Prompted by improving the Debian packaging of GLib to generate most of
the language codes mentioned in the tests, so that we can have better
test coverage.
Signed-off-by: Simon McVittie <smcv@collabora.com>
It’s not feasible to test that the require-same-user flag can cause
authentication to fail, as that would require the build environment to
have two users available. We can, however, test that it passes when
authenticating a client and server running under the same user account.
I have manually tested that the new flag works, by running the following
as user A:
```
`$prefix/gdbus-daemon --print-env &`
gdbus call --session --dest org.freedesktop.DBus --object-path /org/freedesktop/DBus --method org.freedesktop.DBus.ListNames
```
And then running the `gdbus call` command again as user B (with the same
value for `DBUS_SESSION_BUS_ADDRESS` in the environment), which
produces:
```
Error connecting: Unexpected lack of content trying to read a line
```
(an authentication rejection)
Commenting out the use of
`G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER` from
`gdbusdaemon.c`, the `gdbus call` command succeeds for both users.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
This doesn’t change the `GDBusDaemon` behaviour, but does simplify the
code a little.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #1804
This eliminates a common use case for the
`GDBusAuthObserver::authorize-authenticated-peer` signal, which is often
implemented incorrectly by people.
Suggested by Simon McVittie.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Fixes: #1804
These should never have been allowed; they will result in precondition
failures from the `GKeyFile` later on in the code.
A test will be added for this shortly.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Fix an effective regression in commit
7781a9cbd2, which happens when
`convert_path()` is called with a `key` which contains no slashes. In
that case, the `key` is entirely the `basename`.
Prior to commit 7781a9cb, the code worked through a fluke of `i == -1`
cancelling out with the various additions in the `g_memdup()` call, and
effectively resulting in `g_strdup (key)`.
Spotted by Guido Berhoerster.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
gio/glib-compile-resources.c: In function ‘parse_resource_file’:
gio/glib-compile-resources.c:553:3: error: missing initializer for field ‘passthrough’ of ‘GMarkupParser’ {aka ‘struct _GMarkupParser’}
553 | GMarkupParser parser = { start_element, end_element, text };
| ^~~~~~~~~~~~~
gio/gio-tool-tree.c: In function ‘do_tree’:
gio/gio-tool-tree.c:124:22: error: comparison of integer expressions of different signedness: ‘unsigned int’ and ‘int’
124 | for (n = 0; n < level; n++)
| ^
gio/gio-tool-tree.c:197:21: error: comparison of integer expressions of different signedness: ‘unsigned int’ and ‘int’
197 | for (n = 0; n < level; n++)
| ^
gio/gio-tool.c: In function ‘attribute_flags_to_string’:
gio/gio-tool.c:171:17: error: comparison of integer expressions of different signedness: ‘int’ and ‘long unsigned int’
171 | for (i = 0; i < G_N_ELEMENTS (flag_descr); i++)
| ^
gio/glib-compile-schemas.c: In function ‘parse_gschema_files’:
gio/glib-compile-schemas.c:1773:3: error: missing initializer for field ‘passthrough’ of ‘GMarkupParser’ {aka ‘struct _GMarkupParser’}
1773 | GMarkupParser parser = { start_element, end_element, text };
| ^~~~~~~~~~~~~
gio/glib-compile-schemas.c: In function ‘main’:
gio/glib-compile-schemas.c:2176:5: error: missing initializer for field ‘arg_description’ of ‘GOptionEntry’ {aka ‘struct _GOptionEntry’}
2176 | { "allow-any-name", 0, 0, G_OPTION_ARG_NONE, &allow_any_name, N_("Do not enforce key name restrictions") },
| ^
gio/glib-compile-schemas.c: In function ‘key_state_set_range’:
gio/glib-compile-schemas.c:376:17: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘long unsigned int’
376 | for (i = 0; i < G_N_ELEMENTS (table); i++)
| ^
gio/glib-compile-schemas.c: In function ‘key_state_serialise’:
gio/glib-compile-schemas.c:714:29: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘long unsigned int’
714 | for (i = 0; i < size / sizeof (guint32); i++)
| ^
gio/gsettings-mapping.c: In function ‘g_settings_set_mapping_int’:
gio/gsettings-mapping.c:65:23: error: comparison of integer expressions of different signedness: ‘gint64’ {aka ‘long int’} and ‘long unsigned int’
65 | if (0 <= l && l <= G_MAXUINT64)
| ^~
gio/gsettings-mapping.c: In function ‘g_settings_set_mapping_float’:
gio/gsettings-mapping.c:120:23: error: comparison of integer expressions of different signedness: ‘gint64’ {aka ‘long int’} and ‘long unsigned int’
120 | if (0 <= l && l <= G_MAXUINT64)
| ^~
gio/gsettings-mapping.c: In function ‘g_settings_get_mapping_int’:
gio/gsettings-mapping.c:224:27: error: comparison of integer expressions of different signedness: ‘gint64’ {aka ‘long int’} and ‘long unsigned int’
224 | return (0 <= l && l <= G_MAXUINT64);
| ^~
gio/gsettings-mapping.c: In function ‘g_settings_get_mapping_float’:
gio/gsettings-mapping.c:269:27: error: comparison of integer expressions of different signedness: ‘gint64’ {aka ‘long int’} and ‘long unsigned int’
269 | return (0 <= l && l <= G_MAXUINT64);
| ^~
The GDBusConnectionFlags and GDBusServerFlags can affect how we carry
out authentication and authorization, either making it more or less
restrictive, so it's desirable to "fail closed" if a program is compiled
against a new version of GLib but run against an old version.
Signed-off-by: Simon McVittie <smcv@collabora.com>
The intention here was to assert that the length of the password fits
in a gssize. Passwords more than half the size of virtual memory are
probably excessive.
Fixes: a8b204ff "gtlspassword: Forbid very long TLS passwords"
Signed-off-by: Simon McVittie <smcv@collabora.com>
gio/gsettingsschema.c: In function ‘parse_into_text_tables’:
gio/gsettingsschema.c:682:3: error: missing initializer for field ‘passthrough’ of ‘GMarkupParser’ {aka ‘struct _GMarkupParser’}
682 | GMarkupParser parser = { start_element, end_element, text };
| ^~~~~~~~~~~~~
gio/gsettingsschema.c:683:3: error: missing initializer for field ‘gettext_domain’ of ‘TextTableParseInfo’ [-Werror=missing-field-initializers]
683 | TextTableParseInfo info = { summaries, descriptions };
| ^~~~~~~~~~~~~~~~~~
gio/gmenu.c: In function ‘g_menu_remove’:
gio/gmenu.c:483:47: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘guint’ {aka ‘unsigned int’}
483 | g_return_if_fail (0 <= position && position < menu->items->len);
| ^
gio/gmenu.c: In function ‘g_menu_insert_item’:
gio/gmenu.c:165:32: error: comparison of integer expressions of different signedness: ‘gint’ {aka ‘int’} and ‘guint’ {aka ‘unsigned int’}
165 | if (position < 0 || position > menu->items->len)
| ^
gio/glocalfileinfo.c: In function ‘get_access_rights’:
gio/glocalfileinfo.c:932:9: error: comparison of integer expressions of different signedness: ‘uid_t’ {aka ‘unsigned int’} and ‘int’
932 | uid == parent_info->owner ||
| ^~
gio/glocalfileinfo.c: In function ‘read_link’:
gio/glocalfileinfo.c:188:21: error: comparison of integer expressions of different signedness: ‘int’ and ‘guint’ {aka ‘unsigned int’}
188 | if (read_size < size)
| ^
The public API `g_tls_password_set_value_full()` (and the vfunc it
invokes) can only accept a `gssize` length. Ensure that nul-terminated
strings passed to `g_tls_password_set_value()` can’t exceed that length.
Use `g_memdup2()` to avoid an overflow if they’re longer than
`G_MAXUINT` similarly.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #2319
Don’t use an `int`, that’s potentially too small. In practical terms,
this is not a problem, since no socket address is going to be that big.
By making these changes we can use `g_memdup2()` without warnings,
though. Fewer warnings is good.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #2319
Previously, the code in `convert_path()` could not handle keys longer
than `G_MAXINT`, and would overflow if that was exceeded.
Convert the code to use `gsize` and `g_memdup2()` throughout, and
change from identifying the position of the final slash in the string
using a signed offset `i`, to using a pointer to the character (and
`strrchr()`). This allows the slash to be at any position in a
`G_MAXSIZE`-long string, without sacrificing a bit of the offset for
indicating whether a slash was found.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #2319
This allows it to handle strings up to length `G_MAXSIZE` — previously
it would overflow with such strings.
Update the several copies of it identically.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #2319
Previously it was handled as a `gssize`, which meant that if the
`stop_chars` string was longer than `G_MAXSSIZE` there would be an
overflow.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #2319