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 in5c0d4b5061. 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. (cherry picked from commit0834378fb9)
System and Service Manager
Details
Most documentation is available on systemd's website.
Assorted, older, general information about systemd can be found in the systemd Wiki.
Information about build requirements is provided in the README file.
Consult our NEWS file for information about what's new in the most recent systemd versions.
Please see the Code Map for information about this repository's layout and content.
Please see the Hacking guide for information on how to hack on systemd and test your modifications.
Please see our Contribution Guidelines for more information about filing GitHub Issues and posting GitHub Pull Requests.
When preparing patches for systemd, please follow our Coding Style Guidelines.
If you are looking for support, please contact our mailing list, join our IRC channel #systemd on libera.chat or Matrix channel
Stable branches with backported patches are available in the stable repo.
We have a security bug bounty program sponsored by the Sovereign Tech Fund hosted on YesWeHack
Repositories with distribution packages built from git main are available on OBS, and also repositories with packages built from the latest stable release
