Commit Graph
91725 Commits
Author SHA1 Message Date
Armaan Sandhu 7cc0257ba8 strv: measure rebroken lines with utf8_char_console_width() too
strv_rebreak_lines() was the last place left that decoded with the permissive
utf8_encoded_to_unichar() and then asked unichar_console_width() how wide the
result is, so it accepted and measured overlong encodings, surrogates,
noncharacters and the obsolete five and six byte forms that utf8_console_width()
now refuses.

That matters because callers mix the two within a single width computation.
sd-varlink-idl.c sizes its indent with utf8_console_width() and then breaks the
body with strv_rebreak_lines(); verbs.c does the same. One half of the sum
refused a sequence that the other half happily assigned a width to.

Use utf8_char_console_width(), which does the validation and the width in one
step, and advance with utf8_next_char() rather than the decoded length. The
function already refused invalid UTF-8, so the only change is which sequences
count as invalid; it now matches utf8_is_valid(), as everywhere else.
2026-09-22 15:58:57 +02:00
Armaan Sandhu 0834378fb9 string-util,format-table: measure console width with unichar_console_width()
ellipsize_mem() and align_string_mem() open coded the width of a character as
unichar_iswide(c) ? 2 : 1, but unichar_console_width() counts a tab as eight
cells. The two disagreed, and format-table.c uses both: it decides a field is too
wide with utf8_console_width(), then asks ellipsize() to fit it into that many
columns, and ellipsize() believed a tab was one cell. The ellipsized cell then
still overflowed the column, measured by the very function that had just asked
for it to be truncated. A table pinned to table_set_width(20) emitted lines of
25, 44 and 39 columns. align_string_mem() undercounted the same way and so padded
already overlong cells further.

Use unichar_console_width(), split out for this purpose in 5c0d4b5061. While at
it, let align_string_mem() decode with utf8_char_console_width() as well, so that
the second pass shares both the width model and the validity check with the
measuring pass, instead of keeping a more permissive decoder of its own around
for the next caller to trip over. Its "count invalid chars as 1" fallback now
skips the whole rejected sequence rather than one byte, so that the continuation
bytes are not charged a cell each of their own; the branch should be unreachable
anyway, since our caller only gets there after utf8_console_width() succeeded on
the same string.

Note that unichar_console_width() charges a tab a flat eight cells, while a
terminal advances to the next multiple of eight, so this is deliberately an upper
bound: the two agree only when the tab itself starts on a multiple of eight. A
per character helper cannot do better, because a tab's width is a function of the
column it starts in, and neither ellipsize_mem() nor align_string_mem() is told
what column its string starts at. Overestimating is the safe direction: it can
leave a column padded short, but it cannot overflow one.

ascii_ellipsize_mem() equates bytes with character cells, which holds for ASCII
except for the tab, so keep tabs off that fast path. Like the ANSI sequence case
just above it, such strings now take the generic path, which means they get the
Unicode ellipsis and one reserved cell rather than "..." and three, even in a non
UTF-8 locale.
2026-09-22 15:58:57 +02:00
Armaan Sandhu cd51add717 utf8: make utf8_char_console_width() reject what utf8_is_valid() rejects
utf8_char_console_width() decoded with utf8_encoded_to_unichar(), which does not
check for overlong encodings, does not check unichar_is_valid(), and still
accepts the obsolete five and six byte forms. Those checks live in the wrapper
utf8_encoded_valid_unichar(), which is what utf8_is_valid() and ellipsize_mem()
use. Over all 4244897280 NUL free byte strings of length one to four, that is the
whole UTF-8 encoding space, the wrapper agrees with utf8_is_valid_n() everywhere,
while the bare decoder disagrees on 8835838 of them, always by accepting more.

So utf8_console_width() assigned a finite width to strings that utf8_is_valid()
refuses. format-table.c measures a cell with utf8_console_width() and, if it does
not fit, hands it to ellipsize(), which validates strictly, returns NULL, and is
reported as -ENOMEM. A surrogate, overlong, noncharacter or five byte sequence in
any cell therefore failed the whole table with a bogus out of memory error, and
only once the column happened to be narrow enough to require truncation, so
whether it happened at all depended on the width of the user's terminal. At other
widths the invalid sequence was printed to the terminal instead.

Decode with utf8_encoded_valid_unichar() so that how wide we think a string is
agrees with whether we consider it valid UTF-8 in the first place. Invalid cells
are now refused consistently with -EINVAL, the way the sequences that
utf8_encoded_to_unichar() already rejected always were.

Note that for tables this makes the refusal total rather than per field:
table_data_requested_width_height() turns a SIZE_MAX width into -EINVAL, which
table_format() propagates, so a cell in one of the newly rejected encodings now
fails the whole table at every width. systemd-dissect and repart --dry-run put
GPT partition names read straight off the image into cells without filtering
them, so a crafted partition name suppresses the whole listing where before it
cost one field, and only at some terminal widths. That is the intended trade:
the alternative is to keep emitting raw invalid bytes to the terminal at
whichever widths happen not to need truncation. Should degrading the cell rather
than the table turn out to be preferable, the place for it is where the text
enters the table, via utf8_escape_invalid() and friends, not in a helper whose
job is to say how wide a string is.

This also makes the assert(w >= 0) in utf8_escape_non_printable_full() hold by
construction rather than by the accident that its own validation was stricter
than the width helper's.
2026-09-22 15:58:57 +02:00
Frantisek Sumsal efa16c7f31 dns-packet: limit the number of jumps during packet decompression
So far we didn't limit the number of jumps when decompressing a DNS
packet. This can lead to some extra work with specially crafted packets
that send a staircase of thousands of descending compression pointers,
which can then be amplified by referencing such staircase from thousands
of names.

Given that legitimate DNS packets need only a handful of jumps in the
compression chains, let's limit the number of jumps per a single name to
256 (the same limit as, for example, Unbound currently has).

Reported by opensec-intelligence (OpenSec).
2026-09-22 15:55:13 +02:00
Luca Boccassi 726cc309b4 NEWS: open new changelog 2026-09-22 15:12:10 +02:00
Luca Boccassi af6469a83c meson: switch version to 263~devel 2026-09-22 15:12:10 +02:00
Luca Boccassi 8cc40e0c5e Finalize meson.version for v262 2026-09-22 15:12:10 +02:00
Luca Boccassi b9979c1e1a NEWS: finalize 2026-09-22 15:12:10 +02:00
Luca Boccassi 2972f1f047 NEWS: update contributors list 2026-09-22 15:12:10 +02:00
Luca Boccassi 6859ecd916 hwdb: update rules 2026-09-22 15:12:10 +02:00
Zbigniew Jędrzejewski-Szmek 541b1335f5 Rename KExecsCount to KExecCount 2026-09-22 14:38:02 +02:00
Daan De Meyer cfd2f7c73e namespace-util: fail if we cannot become root when entering a userns
namespace_enter() tried to become root after joining a user namespace
but ignored failures, so if root wasn't mapped we'd just carry on with
our original UID/GID. Let's make that an error instead.

Dropping supplementary groups stays best effort, as setgroups() might
be denied (e.g. by the nsresourced BPF LSM) even when root is mapped.

Some callers do need to enter namespaces without root, so add
NAMESPACE_ENTER_KEEP_UID_GID_IF_ROOT_UNMAPPED for those. It's used by
systemd-analyze unit-shell and by the credential refresh in the user
manager. Everything else enters containers or namespaces we allocated
ourselves, where root is always mapped.
2026-09-22 13:48:24 +02:00
Zbigniew Jędrzejewski-Szmek 63a7cf844d NEWS: some tweaks before release
Introspection is implemented for everything that has a command-line
parser, not only for select binaries.

Standarize on "rate-limit" as the spelling in docs.

Various other smaller tweaks and clarifications.
2026-09-22 12:47:54 +02:00
Yu Watanabe 6a131b32e0 include: fix limits.h override
This is especially necessary since GCC 16.x.

=====
$ gcc --version
gcc (GCC) 16.2.1 20260819 (Red Hat 16.2.1-2)
Copyright (C) 2026 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
=====

Without this change, /usr/include/limits.h is not included, hence POSIX
constants are not defined:
=====
$ echo '#include <limits.h>' | gcc -E -H -isystem ~/git/systemd/src/include/musl - 2>&1 >/dev/null | grep '^\..*limit'
. /home/watanabe/git/systemd/src/include/musl/limits.h
.. /usr/lib/gcc/x86_64-redhat-linux/16/include/limits.h
... /usr/lib/gcc/x86_64-redhat-linux/16/include/syslimits.h
=====

With this change, /usr/include/limits.h is included, thus POSIX
constants are defined:
=====
$ echo '#include <limits.h>' | gcc -E -H -isystem ~/git/systemd/src/include/musl - 2>&1 >/dev/null | grep '^\..*limit'
. /home/watanabe/git/systemd/src/include/musl/limits.h
.. /usr/lib/gcc/x86_64-redhat-linux/16/include/limits.h
... /usr/include/limits.h
...... /usr/include/linux/limits.h
.. /usr/lib/gcc/x86_64-redhat-linux/16/include/limits.h
=====

Replaces #43824.
2026-09-22 18:14:12 +09:00
Yu Watanabe e362a4efcb namespace,condition: drop invalid _const_ attributes
The _const_ attribute can be only used for functions.

Fixes the following warnings on Fedora rawhide:
```
../src/core/namespace.h:260:75: warning: '__const__' attribute only applies to functions [-Wignored-attributes]
  260 | char* bpf_delegate_to_string(uint64_t u, const char * (*parser)(uint64_t) _const_);
      |                                                                           ^
../src/basic/../fundamental/macro.h:80:32: note: expanded from macro '_const_'
   80 | #define _const_ __attribute__((__const__))
      |                                ^
In file included from ../src/core/unit.c:24:
../src/shared/condition.h:87:63: warning: '__const__' attribute only applies to functions [-Wignored-attributes]
   87 | typedef const char* (*condition_to_string_t)(ConditionType t) _const_;
      |                                                               ^
../src/basic/../fundamental/macro.h:80:32: note: expanded from macro '_const_'
   80 | #define _const_ __attribute__((__const__))
      |                                ^
```
2026-09-22 02:46:35 +09:00
Val Packett d4f1a76a2e udev: rules: order ID_BUS assignment by specificity / bus nesting depth
Only PCI was treated as a "less specific" bus that should not be
assigned if USB was already assigned, so non-PCI USB controllers
(under platform/DT or ACPI) would have all their devices *not*
treated as USB at all, resulting in external peripherals being
treated as internal ones on DT platforms.

Clarify these assignments into specificity/nesting groups instead
of having some arbitrary "X must be before Y" comments.

Fixes a4381cae8b.
2026-09-21 23:46:17 +09:00
Lennart Poettering e355960ac1 Various imds fixes (#43772) 2026-09-21 13:58:58 +02:00
Yu Watanabe a6653a56c9 test-network: do not try to set too small quanta for ets
Since kernel v7.3 the kernel clamp quanta:
https://github.com/torvalds/linux/commit/1c38487f46b243bfeefec0c0c86023a3904f2214

So, too small values are now calmped to 256.
Let's change the values used in the test so that they are not clamped.
2026-09-21 13:31:06 +02:00
Lennart Poettering ada6409d6a vmspawn: bring external and internal enum value names back in sync
We generally want that the exposed strings for enum values and the
internal names for them stay in sync. Let's make sure this is the case
for the ConfidentialComputing enum.

This just changes the internal names, so that they match the external
ones. No user visible change, just some search and replace.
2026-09-21 12:37:25 +02:00
Luca Boccassi 5d414df040 NEWS: drop truncated sentence 2026-09-21 11:17:45 +02:00
zouge666 07cf0376a8 dissect-image: prevent start+size LBA overflow 2026-09-21 10:10:22 +02:00
Jan Kuparinen e96ff3b5b9 po: Translated using Weblate (Finnish)
Currently translated at 100.0% (286 of 286 strings)

Co-authored-by: Jan Kuparinen <copper_fin@hotmail.com>
Translate-URL: https://translate.fedoraproject.org/projects/systemd/main/fi/
Translation: systemd/main
2026-09-19 05:16:58 +09:00
Weblate Translation Memory 96347f83cc po: Translated using Weblate (Finnish)
Currently translated at 100.0% (286 of 286 strings)

po: Translated using Weblate (Finnish)

Currently translated at 100.0% (286 of 286 strings)

po: Translated using Weblate (Finnish)

Currently translated at 100.0% (286 of 286 strings)

po: Translated using Weblate (Finnish)

Currently translated at 100.0% (286 of 286 strings)

po: Translated using Weblate (Finnish)

Currently translated at 100.0% (286 of 286 strings)

po: Translated using Weblate (Finnish)

Currently translated at 100.0% (286 of 286 strings)

po: Translated using Weblate (Finnish)

Currently translated at 100.0% (286 of 286 strings)

po: Translated using Weblate (Finnish)

Currently translated at 100.0% (286 of 286 strings)

po: Translated using Weblate (Finnish)

Currently translated at 100.0% (286 of 286 strings)

po: Translated using Weblate (Finnish)

Currently translated at 100.0% (286 of 286 strings)

po: Translated using Weblate (Finnish)

Currently translated at 100.0% (286 of 286 strings)

po: Translated using Weblate (Finnish)

Currently translated at 100.0% (286 of 286 strings)

po: Translated using Weblate (Finnish)

Currently translated at 100.0% (286 of 286 strings)

po: Translated using Weblate (Finnish)

Currently translated at 100.0% (286 of 286 strings)

po: Translated using Weblate (Finnish)

Currently translated at 100.0% (286 of 286 strings)

Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Translate-URL: https://translate.fedoraproject.org/projects/systemd/main/fi/
Translation: systemd/main
2026-09-19 05:16:58 +09:00
Anders Jonsson a269dda363 po: Translated using Weblate (Swedish)
Currently translated at 100.0% (286 of 286 strings)

Co-authored-by: Anders Jonsson <anders.jonsson@norsjovallen.se>
Translate-URL: https://translate.fedoraproject.org/projects/systemd/main/sv/
Translation: systemd/main
2026-09-19 05:16:58 +09:00
Daan De Meyer 477a4c97e0 ci: shorten Claude review comments and raise the bar on re-reviews
The Claude review workflow posted long, padded inline comments, and every
force push produced a fresh batch of new findings on code that had not
changed. Both make authors stop reading the reviews.

Add a comment style section to the prompt that limits each comment to the
problem and the obvious fix, and truncate anything over 1000 characters in
the post job. Track the number of completed reviews and the last reviewed
head in a hidden state line in the tracking comment. Each successful review
narrows the severities that may be posted: everything on the first review,
no nits on the second, and only must-fix findings from the third on. The
post job enforces the policy so it holds even if the model ignores the
prompt, and reviewers are told to range-diff against the previous head and
skip non-must-fix findings on unchanged code. Commenting "@claude review
full" resets the count for that run.
2026-09-18 20:28:35 +02:00
Lennart Poettering 41bf07afe1 man: add missing = 2026-09-18 20:23:00 +02:00
Zbigniew Jędrzejewski-Szmek 4fb9fbd68a man,doc: fix typos (#43766) 2026-09-17 20:41:37 +02:00
Zbigniew Jędrzejewski-Szmek a2b81310af test: give the D-Bus reconnect checks their own integration test (#43776)
`TEST-23-UNIT-FILE.dbus-reconnect.sh` SIGKILLs `dbus.service` three
times. Nothing reconnects to the new broker, so logind keeps running
with `org.freedesktop.login1` unowned for the rest of the boot —
activation can't fix it either, as `dbus-org.freedesktop.login1.service`
is already active, so the job finishes at once and the name never
returns.

That leaks into the subtests after it. `statedir.sh`, the first to start
`user@0.service`, spends 2 × 25 s in user-runtime-dir on logind
properties, and where pam_systemd can't use Varlink (memory-max= & co.
in the PAM stack) it blocks in `CreateSession()` for 2 min, past
user@.service's 90 s TimeoutStartSec — failing, and pointing at a
subtest that has nothing to do with the bus.

Hit this in hyperscale v261.3 release test for centos9:

https://artifacts.dev.testing-farm.io/01c1c68b-da64-4b9e-b163-eb3459aabe79/work-upstreamjejyd7ep/log.txt
2026-09-17 15:38:16 +02:00
Ivan Kruglov d4d31c1859 test: exempt the broker from its start rate limit in TEST-95 2026-09-17 04:51:36 -07:00
Ivan Kruglov 621df84009 test: give the D-Bus reconnect checks their own integration test
Killing the broker is destructive well beyond the units under test: nothing
reconnects to the new one, so logind for instance keeps running with
org.freedesktop.login1 unowned for the rest of the boot. As a subtest of
TEST-23-UNIT-FILE that leaked into everything running after it, and
statedir.sh, the first one to start user@0.service, then spent 25s per logind
property in user-runtime-dir and, where pam_systemd can't use Varlink, blocked
in CreateSession() past user@.service's 90s TimeoutStartSec and failed — with
the failure pointing at a subtest that has nothing to do with the bus.

In its own test the damage dies with the machine.
2026-09-17 04:51:29 -07:00
Daniel Wagenknecht d8b9dacaf9 timedate: use SymlinkFlags enum members for flags
The flags to pass to symlinkat_atomic_full are defined in the
SymlinkFlags enum type. The previous code passed the result of a boolean
check operation directly instead of using flags.

Be explicit about the value to pass instead of relying on true
corresponding to the enum value for the SYMLINK_MAKE_RELATIVE flag.

Signed-off-by: Daniel Wagenknecht <dwagenknecht@emlix.com>
2026-09-17 13:00:17 +02:00
Yu Watanabe b36cf41a89 README.md: fix invalid </br> tags in badge list 2026-09-17 11:49:45 +09:00
Yu Watanabe 24de80f596 docs: fix typos and grammar in NEWS, README and TODO 2026-09-17 11:49:45 +09:00
Yu Watanabe 496712eddc docs: fix typos and grammar in various documents 2026-09-17 11:49:45 +09:00
Yu Watanabe 194c72b37f man: fix parameter controlling activatable names query for sd_bus_list_names()
The second conditional checked "acquired", but the ListActivatableNames
call is governed by the "activatable" argument.
2026-09-17 11:49:45 +09:00
Yu Watanabe 83c4191e25 man: fix inverted -ENODATA description for sd_bus_message_get_reply_cookie()
-ENODATA is returned when the message carries no (reply) cookie, but the
text stated the message "carries a reply cookie field". Say it does not
carry one.
2026-09-17 11:49:45 +09:00
Yu Watanabe 8787df83fe man: several fixlets for documentation of sd_bus_message_read_array()
- It does not accept NUL for type.
- ret_size is zero and ret_ptr is non-NULL when it returns positive.
- Fixed argument names: ptr -> ret_ptr, size -> ret_size.
2026-09-17 11:49:45 +09:00
Yu Watanabe 15bd45d113 man: fix typos and grammar in various man pages 2026-09-17 02:25:12 +09:00
Lennart Poettering b1cb951a6f update TODO 2026-09-16 17:50:03 +02:00
Arian van Putten bb2c842b1f imds: actually default to the build-time IMDS network mode
The imds-network= meson option has never had an effect on the generated
network configuration. It arrived in 168a7f7770 together with the IMDS
generator, which wired IMDS_NETWORK_LOCKED_DEFAULT (turned into
IMDS_NETWORK_DEFAULT by c3e4e8a527) into the generator's
arg_network_mode. But the generator only ever compares that variable
against IMDS_NETWORK_OFF, to decide whether to pull
systemd-imds-early-network.service into the initial transaction, and
"off" is not one of the option's choices. It also never forwards the
mode on to systemd-imds-early-network.service, neither as a command
line switch nor via a drop-in.

85-imds-early.network is written by systemd-imds-early-network.service,
which runs "systemd-imdsd --setup-network", and that code path's
arg_network_mode was left at _IMDS_NETWORK_MODE_INVALID. As
setup_network() requires "!= IMDS_NETWORK_UNLOCKED" before emitting the
"prohibit" routes, the unset sentinel behaves exactly like "locked".

At first that went unnoticed, because the option defaulted to "locked"
as well: the documented default matched the implemented behaviour by
accident, and only "-Dimds-network=unlocked" was quietly ignored.
6240d420d6 ("meson: unlock imds network by default") then flipped the
default by reordering the option's choices, i.e. moved a macro that
nothing consumed. From that point on the default was wrong for
everybody: unless systemd.imds.network= is passed on the kernel command
line, every generated network file locks the IMDS endpoint down, no
matter how the build is configured. ac64b2dfa3 later documented the new
default in man:systemd-imdsd@.service(8) (#42687), which meant the
documentation now described behaviour that does not exist.

In practice this rarely became visible until the previous commit, since
systemd-imdsd --setup-network mostly lost its race against udev and
wrote no network file at all.

Initialize arg_network_mode from IMDS_NETWORK_DEFAULT, the same way
imds-generator.c does. No other code distinguishes the INVALID sentinel
from a real mode; the remaining users compare against IMDS_NETWORK_OFF
and IMDS_NETWORK_UNLOCKED only. The kernel command line still overrides
the build-time default, and the only difference in the generated network
file are the two "prohibit" routes: the fwmark routing table and the
matching routing policy rule are written in either mode, as before.
2026-09-16 12:45:11 +02:00
Arian van Putten 7bd5496bef imds: make DMI device ordering of early network unit effective
systemd-imds-early-network.service carries
After=sys-devices-virtual-dmi-id.device, so that systemd-imdsd
--setup-network sees the IMDS_* properties that udev applies to the DMI
device from hwdb data. Ordering dependencies only take effect if both
units are part of the same transaction though, and nothing ever pulled
the device unit in: the generator hooks the service into
sysinit.target.wants/ only, and the unit sets DefaultDependencies=no.
The ordering was therefore a nop, and the service raced udev's
coldplugging.

When it lost that race the failure was silent: smbios_server_info()
found no IMDS_VENDOR= property, so no endpoint got configured,
cmdline_run() returned EXIT_NOTCONFIGURED, the unit's
SuccessExitStatus=NOTCONFIGURED reported that as success, and no
85-imds-early.network was written at all.

Give the unit the same drop-in we already write for
systemd-imdsd@.service, which adds Wants= in addition to After= for the
device unit, and factor it out into a helper. We only get here once the
DMI device has been found in the hwdb, hence pulling the device unit
into the transaction is safe.

Note that with the race fixed I have yet to see systemd-imdsd actually
work in locked mode: it appears to end up locked out by the "prohibit"
route itself, despite the fwmark bypass. That is a separate issue, and
left for somebody else to look into.
2026-09-16 12:45:11 +02:00
Luca Boccassi f3880debd7 meson: bump version to v262~rc3 2026-09-15 12:25:09 +01:00
Luca Boccassi 745b63fbb0 NEWS: finalize time and place 2026-09-15 12:25:09 +01:00
Luca Boccassi 0bf0584123 NEWS: update contributors list 2026-09-15 12:25:09 +01:00
Luca Boccassi a491517a09 hwdb: update rules 2026-09-15 12:25:09 +01:00
Lennart Poettering e2c84823ed mountpoint-util: improve logging when kernel lacks support for a certain fs type
Inspired by #43752
2026-09-14 16:28:23 +02:00
Lennart Poettering f74b848a17 sysupdate: undo some accidental field renaming (#43707)
This undoes some of the work in #43603 which was a follow-up to #42900
which – unintentionally I'd claim – renamed some JSON fields. Instead of
setting those changes in stone we should undo them.

Not just to not needlessly break compat, but more importantly because
the old names made more sense given the underlying .feature file knobs.
2026-09-14 16:27:49 +02:00
Lennart Poettering f0baee29b3 sysupdate: change "appstream" json prop back to "appStream"
Similar as the previous commit: the field was renamed by accident, and
we should revert to the old name to not break compat needlessly, and
because the old name actually made sense, given the underlying .transfer
file knob is AppStream=
2026-09-14 15:15:58 +02:00
Lennart Poettering f05a0cef9f sysupdate: rename isEnabled to enabled
The "isEnabled" name was changed from "enabled" post v261 by accident
(because a6f7ded859 replaced json
formatting via table formatter to a native json generator which was
introduced for varlink, which changed the names). THis was later made
official in #43603, but it should rather have changed things back to the
original name, in particular as the underling .feature file field
actually is called "Enabled=" and not "IsEnabled=".

We really should take care to generate the same names for Varlink JSON
data as for the data returned by the systemd-sysupdate cli.
a6f7ded859 ensured that, so that's great.
But at the same time I think the varlink names should be adjusted to the
old names, since varlink support for this was just added in this cycle.

Given that v262 is not tagged yet, let's now revert to the old name.
2026-09-14 14:33:33 +02:00
Chris Down 17d46d0442 test: drop unused include from test-parse-util.c (#43757)
Fix clang-tidy regression:

```
../src/test/test-parse-util.c:11:1: error: included header string-util.h is not used directly [misc-include-cleaner,-warnings-as-errors]
   11 | #include "string-util.h"
      | ^~~~~~~~~~~~~~~~~~~~~~~~
   12 | #include "tests.h"
```

Follow-up for efdc4b0cc7
2026-09-14 17:55:21 +08:00