The past few commits introduced the concept of known-good offsets in the
offset table (which is used for variable-width arrays and tuples).
Good offsets are ones which are non-overlapping with all the previous
offsets in the table.
If a bad offset is encountered when indexing into the array or tuple,
the cached known-good offset index will not be increased. In this way,
all child variants at and beyond the first bad offset can be returned as
default values rather than dereferencing potentially invalid data.
In this case, there was no information about the fact that the indexes
between the highest known-good index and the requested one had been
checked already. That could lead to a pathological case where an offset
table with an invalid first offset is repeatedly checked in full when
trying to access higher-indexed children.
Avoid that by storing the index of the highest checked offset in the
table, as well as the index of the highest good/ordered offset.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #2121
This is similar to the earlier commit which prevents child elements of a
variable-sized array from overlapping each other, but this time for
tuples. It is based heavily on ideas by William Manley.
Tuples are slightly different from variable-sized arrays in that they
contain a mixture of fixed and variable sized elements. All but one of
the variable sized elements have an entry in the frame offsets table.
This means that if we were to just check the ordering of the frame
offsets table, the variable sized elements could still overlap
interleaving fixed sized elements, which would be bad.
Therefore we have to check the elements rather than the frame offsets.
The logic of checking the elements up to the index currently being
requested, and caching the result in `ordered_offsets_up_to`, means that
the algorithmic cost implications are the same for this commit as for
variable-sized arrays: an O(N) cost for these checks is amortised out
over N accesses to O(1) per access.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Fixes: #2121
This is similar to the earlier commit which prevents child elements of a
variable-sized array from overlapping each other, but this time for
tuples. It is based heavily on ideas by William Manley.
Tuples are slightly different from variable-sized arrays in that they
contain a mixture of fixed and variable sized elements. All but one of
the variable sized elements have an entry in the frame offsets table.
This means that if we were to just check the ordering of the frame
offsets table, the variable sized elements could still overlap
interleaving fixed sized elements, which would be bad.
Therefore we have to check the elements rather than the frame offsets.
The logic of checking the elements up to the index currently being
requested, and caching the result in `ordered_offsets_up_to`, means that
the algorithmic cost implications are the same for this commit as for
variable-sized arrays: an O(N) cost for these checks is amortised out
over N accesses to O(1) per access.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Fixes: #2121
This reduces a few duplicate calls to `g_variant_type_info_query()` and
explains why they’re needed.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #2121
If different elements of a variable sized array can overlap with each
other then we can cause a `GVariant` to normalise to a much larger type.
This commit changes the behaviour of `GVariant` with non-normal form data. If
an invalid frame offset is found all subsequent elements are given their
default value.
When retrieving an element at index `n` we scan the frame offsets up to index
`n` and if they are not in order we return an element with the default value
for that type. This guarantees that elements don't overlap with each
other. We remember the offset we've scanned up to so we don't need to
repeat this work on subsequent accesses. We skip these checks for trusted
data.
Unfortunately this makes random access of untrusted data O(n) — at least
on first access. It doesn't affect the algorithmic complexity of accessing
elements in order, such as when using the `GVariantIter` interface. Also:
the cost of validation will be amortised as the `GVariant` instance is
continued to be used.
I've implemented this with 4 different functions, 1 for each element size,
rather than looping calling `gvs_read_unaligned_le` in the hope that the
compiler will find it easy to optimise and should produce fairly tight
code.
Fixes: #2121
The following few commits will add a couple of new fields to
`GVariantSerialised`, and they should be zero-filled by default.
Try and pre-empt that a bit by zero-filling `GVariantSerialised` by
default in a few places.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #2121
If a seccomp policy is set up incorrectly so that it returns `EPERM` for
`close_range()` rather than `ENOSYS` due to it not being recognised, no
error would previously be reported from GLib, but some file descriptors
wouldn’t be closed, and that would cause a hung zombie process. The
zombie process would be waiting for one half of a socket to be closed.
Fix that by correctly propagating errors from `close_range()` back to the
parent process so they can be reported correctly.
Distributions which aren’t yet carrying the Docker fix to correctly
return `ENOSYS` from unrecognised syscalls may want to temporarily carry
an additional patch to fall back to `safe_fdwalk()` if `close_range()`
fails with `EPERM`. This change will not be accepted upstream as `EPERM`
is not the right error for `close_range()` to be returning.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Fixes: #2580
g_get_user_database_entry() uses variable pwd to store the contents of
the call to getpwnam_r(), then capitalises the first letter of pw_name
with g_ascii_toupper (pw->pw_name[0]).
However, as per the getpwnam manpage, the result of that call "may point
to a static area". When this happens, GLib is trying to edit static
memory which belongs to a shared library, so segfaults.
Instead, copy pw_name off to a temporary variable, set uppercase on
that variable, and use the variable to join into the desired string.
Free the new variable after it is no longer needed.
Signed-off-by: Jamie Bainbridge <jamie.bainbridge@gmail.com>
Although unlikely, these functions can fail, e.g. if we run out of file
descriptors. Check for errors to improve robustness. This is especially
important now that I changed our use of dupfd_cloexec() to avoid
returning fds smaller than the largest fd in target_fds. An application
that attempts to remap to the highest-allowed fd value deserves at least
some sort of attempt at error reporting, not silent failure.
We currently dup all source fds to avoid possible conflation with the
target fds, but fail to consider that the result of a dup might itself
conflict with one of the target fds. Solve this the easy way by duping
all source_fds to values that are greater than the largest fd in
target_fds.
Fixes#2503
In case child_err_report_fd conflicts with one of the target_fds, the
code here is careful to dup child_err_report_fd in order to avoid
conflating the two. It was a good idea, but evidently was not tested,
because the newly-created fd is not created with CLOEXEC set. This means
it stays open in the child process, causing the parent to hang forever
waiting to read from the other end of the pipe. Oops!
The fix is simple: just set CLOEXEC. This removes our only usage of the
safe_dup() function, so it can be dropped.
Fixes#2506
Previously, these would have done 2**32 replacements, and the first one
would have consumed 6GB of memory in the process. They now match what
Python `str.replace()` does.
Reproduces: https://gitlab.gnome.org/GNOME/glib/-/issues/2452
Signed-off-by: Simon McVittie <smcv@collabora.com>
This matches the behaviour of Python `str.replace()`, and avoids carrying
out 2**32 replacements before n wraps around, which is almost certainly
not what we want.
Resolves: https://gitlab.gnome.org/GNOME/glib/-/issues/2452
Signed-off-by: Simon McVittie <smcv@collabora.com>
These are taken from another project (steam-runtime-tools) where I
implemented a similar replace method before realising that more recent
GLib versions had g_string_replace().
Signed-off-by: Simon McVittie <smcv@collabora.com>
When using TAP we want every single line to be one of the following:
- a valid TAP clause
- a comment
- a blank line
Typical explicit test logs are single line comments, but in some cases
we might end up printing debug messages from libraries, and those may
contain multiple lines. When that happens, we break the TAP and fail the
test in conditions entirely outside of our control.
One option to avoid outright failure is to always prepend each line of a
messge with `#`, to ensure that the whole thing is considered a comment.
If the same `GKeyFile` is reused to load multiple different key files,
any loads after the first which encounter translated keys will crash,
because clearing the data from the first load cleared the cached
language names, but didn’t clear `checked_locales`, so they were never
reloaded.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Fixes: #2361
It should not be possible for `->locales` to be set without
`->checked_locales` being set, so drop the redundant check. This helps
with branch code coverage.
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
The changes in 4273c43902 did not guard
macros in `gatomic.h` which use `glib_typeof`. This meant that when
552b8fd862 was committed, moving the
include of `<type_traits>` under such a guard, these macros were still
trying to use it. This broke the build of at least vte.
Fix this by guarding the API break in `gatomic.h` too.
The doc used different phrasing for the same thing, e.g. "if any thread"
vs "any other thread."
Also make it clear that trying to take a write lock while already having
a lock, or trying to take a read lock while having a write lock, is
undefined.
When included inside an `extern "C"` block, this causes build failures
that look something like:
/usr/include/c++/10/type_traits:2930:3: error: template with C linkage
2930 | template<typename _Fn, typename... _Args>
| ^~~~~~~~
../../disas/arm-a64.cc:20:1: note: ‘extern "C"’ linkage started here
20 | extern "C" {
| ^~~~~~~~~~
Commit 4273c43902 made this opt in for
projects which are defining `GLIB_VERSION_MIN_REQUIRED`, but the include
of `<type_traits>` via `gmacros.h` was not included in this. If we move
the include out to the places where `glib_typeof` is called, we can make
it covered by this macro too, and save a few consumers from FTBFSing.
That also means that, if you don't want to fix your use of the headers,
and as long as this version is sufficient for you, a quick workaround is
to define `GLIB_VERSION_MIN_REQUIRED` to `GLIB_VERSION_2_66` or lower.
Suggested by Simon McVittie.
Alternative to: https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1935
Fixes: https://gitlab.gnome.org/GNOME/glib/-/issues/2331
The `source_fds`/`target_fds` functionality is not supported on Windows
at the moment.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Fixes: #2097
This should introduce no functional changes, but condenses the variants
of the internal spawn implementation down to be more like `gspawn.c`.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #2097
I realise Windows uses handles rather than PIDs, but given that there
are multiple platform-specific implementations of the public
`g_spawn_*()` API, I think it is less confusing for them all to use the
same naming scheme.
This introduces no functional changes.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
This is a simple wrapper around the new source/target FD mapping
functionality in `fork_exec()`.
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
Helps: #2097