Skip to content

Fix 32-bit Unicode truncation and QChar assertion crashes#633

Draft
wineee wants to merge 1 commit intolxqt:masterfrom
wineee:QChar
Draft

Fix 32-bit Unicode truncation and QChar assertion crashes#633
wineee wants to merge 1 commit intolxqt:masterfrom
wineee:QChar

Conversation

@wineee
Copy link
Copy Markdown
Contributor

@wineee wineee commented Apr 17, 2026

This commit addresses crashes caused by Qt 6 enforcing strict range checks (<= 0xFFFF) in the QChar(uint) constructor, as well as fixing internal truncation issues for characters outside the Basic Multilingual Plane (BMP).

  • Converted TerminalDisplay::charClass to return char32_t instead of QChar, fixing assertions in word extraction algorithms.
  • Replaced QChar-based unicode checks directly initialized from wchar_t with safe static QChar properties (QChar::category, QChar::isSpace) acting on char32_t values.
  • Fixed Character(quint16 _c) constructor inadvertently truncating 32-bit codepoints.
  • Converted CompactHistoryLine properties to uint* rather than quint16* to prevent scrollback from discarding upper bits of wide characters.

fix: #632

@wineee wineee marked this pull request as draft April 17, 2026 10:20
This commit addresses crashes caused by Qt 6 enforcing strict range
checks (<= 0xFFFF) in the QChar(uint) constructor, as well as fixing internal
truncation issues for characters outside the Basic Multilingual Plane (BMP).

- Converted TerminalDisplay::charClass to return char32_t instead of QChar,
  fixing assertions in word extraction algorithms.
- Replaced QChar-based unicode checks directly initialized from wchar_t
  with safe static QChar properties (QChar::category, QChar::isSpace) acting
  on char32_t values.
- Replaced slow and unsafe character width calculations with a fast-path
  surrogate check (QChar::requiresSurrogates), only allocating QStrings
  for extended glyphs, avoiding rendering loop performance penalties.
- Fixed Character(quint16 _c) constructor inadvertently truncating 32-bit
  codepoints.
- Converted CompactHistoryLine properties to uint* rather than quint16* to
  prevent scrollback from discarding upper bits of wide characters.
Comment thread lib/Character.h
* @param _r A set of rendition flags which specify how this character is to be drawn.
*/
inline Character(quint16 _c = ' ',
inline Character(wchar_t _c = ' ',
Copy link
Copy Markdown
Contributor Author

@wineee wineee Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

KDE/konsole@5128781

kconsole switched from quint16 to uint, and qtermwidget was changed to wchat_t, but it seems some parts were missed.

Starting from Qt6, some function parameters of QChar have been changed from uint to char32_t, which is a C++ standard type. I think it might be better to switch wchar_t to char32_t...

Comment thread lib/TerminalDisplay.cpp
bool lineDraw = isLineChar(newLine[x+0]);
bool doubleWidth = (x+1 == columnsToUpdate) ? false : (newLine[x+1].character == 0);
int charWidth = fm.horizontalAdvance(QChar(c));
int charWidth = QChar::requiresSurrogates(c) ? fm.horizontalAdvance(QString::fromWCharArray(&c, 1)) : fm.horizontalAdvance(QChar(static_cast<ushort>(c)));
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not clear if there is a more efficient approach here, as konsole's logic has changed a bit and didn't use horizontalAdvance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

If the terminal is compiled in debug mode, running systemd-analyze security will crash:ASSERT: "rc <= 0xffff"

1 participant