From 88aa47c377b21b0d6489fdb527e825ca708d8973 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Sun, 30 Nov 2025 17:54:33 +0100 Subject: [PATCH] Add qt.workarounds.disable_accessibility setting This disables accessibility with Qt 6.10.1, which causes frequent segfaults. Closes #8797 --- doc/changelog.asciidoc | 12 +++++++++ doc/help/settings.asciidoc | 19 +++++++++++++ qutebrowser/config/configdata.yml | 13 +++++++++ qutebrowser/config/qtargs.py | 10 +++++++ tests/unit/config/test_qtargs.py | 45 ++++++++++++++++++++++++++++++- 5 files changed, 98 insertions(+), 1 deletion(-) diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc index 8fc476f93..f9e2766cd 100644 --- a/doc/changelog.asciidoc +++ b/doc/changelog.asciidoc @@ -15,6 +15,18 @@ breaking changes (such as renamed commands) can happen in minor releases. // `Fixed` for any bug fixes. // `Security` to invite users to upgrade in case of vulnerabilities. +[[v3.6.3]] +v3.6.3 (unreleased) +------------------- + +Fixed +~~~~~ + +- New `qt.workarounds.disable_accessibility` setting, which disables Chromium + accessibility support. By default, is it set to `auto`, which only disables + accessibility on Qt versions with known issues. This works around a bug in Qt + 6.10.1 causing frequent segfaults (#8797). + [[v3.6.2]] v3.6.2 (2025-11-27) ------------------- diff --git a/doc/help/settings.asciidoc b/doc/help/settings.asciidoc index 2160a15f9..434260b20 100644 --- a/doc/help/settings.asciidoc +++ b/doc/help/settings.asciidoc @@ -302,6 +302,7 @@ |<>|Force software rendering for QtWebEngine. |<>|Turn on Qt HighDPI scaling. |<>|Disable accelerated 2d canvas to avoid graphical glitches. +|<>|Disable accessibility to avoid crashes on Qt 6.10.1. |<>|Disable the Hangouts extension. |<>|Work around locale parsing issues in QtWebEngine 5.15.3. |<>|Delete the QtWebEngine Service Worker directory on every start. @@ -3996,6 +3997,24 @@ Valid values: Default: +pass:[auto]+ +[[qt.workarounds.disable_accessibility]] +=== qt.workarounds.disable_accessibility +Disable accessibility to avoid crashes on Qt 6.10.1. + +This setting requires a restart. + +This setting is only available with the QtWebEngine backend. + +Type: <> + +Valid values: + + * +always+: Disable renderer accessibility + * +auto+: Disable on Qt versions with known issues, enable otherwise + * +never+: Enable renderer accessibility + +Default: +pass:[auto]+ + [[qt.workarounds.disable_hangouts_extension]] === qt.workarounds.disable_hangouts_extension Disable the Hangouts extension. diff --git a/qutebrowser/config/configdata.yml b/qutebrowser/config/configdata.yml index 68c36ccd0..b221a70dc 100644 --- a/qutebrowser/config/configdata.yml +++ b/qutebrowser/config/configdata.yml @@ -422,6 +422,19 @@ qt.workarounds.disable_hangouts_extension: disabled to avoid crashes on Qt 6.5.0 to 6.5.3 if dark mode is enabled, as well as on Qt 6.6.0. +qt.workarounds.disable_accessibility: + type: + name: String + valid_values: + - always: Disable renderer accessibility + - auto: Disable on Qt versions with known issues, enable otherwise + - never: Enable renderer accessibility + default: auto + backend: QtWebEngine + restart: true + desc: >- + Disable accessibility to avoid crashes on Qt 6.10.1. + ## auto_save auto_save.interval: diff --git a/qutebrowser/config/qtargs.py b/qutebrowser/config/qtargs.py index f89f62733..c96cd61b1 100644 --- a/qutebrowser/config/qtargs.py +++ b/qutebrowser/config/qtargs.py @@ -362,6 +362,16 @@ _WEBENGINE_SETTINGS: dict[str, dict[Any, Optional[_SettingValueType]]] = { and versions.webengine < utils.VersionNumber(6, 8, 2) else None, }, + 'qt.workarounds.disable_accessibility': { + 'always': '--disable-renderer-accessibility', + 'never': None, + # WORKAROUND for https://qt-project.atlassian.net/browse/QTBUG-142320 + 'auto': lambda versions: '--disable-renderer-accessibility' + if machinery.IS_QT6 + and versions.webengine + and versions.webengine == utils.VersionNumber(6, 10, 1) + else None, + }, } diff --git a/tests/unit/config/test_qtargs.py b/tests/unit/config/test_qtargs.py index 49d02e107..b29949628 100644 --- a/tests/unit/config/test_qtargs.py +++ b/tests/unit/config/test_qtargs.py @@ -12,7 +12,7 @@ import pytest from qutebrowser.qt import machinery from qutebrowser import qutebrowser from qutebrowser.config import qtargs, configdata -from qutebrowser.utils import usertypes, version +from qutebrowser.utils import usertypes, version, utils @pytest.fixture @@ -52,6 +52,7 @@ def reduce_args(config_stub, version_patcher, monkeypatch): config_stub.val.scrolling.bar = 'never' config_stub.val.qt.chromium.experimental_web_platform_features = 'never' config_stub.val.qt.workarounds.disable_accelerated_2d_canvas = 'never' + config_stub.val.qt.workarounds.disable_accessibility = 'never' monkeypatch.setattr(qtargs.utils, 'is_mac', False) # Avoid WebRTC pipewire feature monkeypatch.setattr(qtargs.utils, 'is_linux', False) @@ -117,6 +118,14 @@ def test_no_webengine_available(monkeypatch, config_stub, parser, stubs): assert args == [sys.argv[0]] +_XFAIL_FUTURE_QT = ( + pytest.mark.xfail( + utils.VersionNumber(6, 11) not in version.WebEngineVersions._CHROMIUM_VERSIONS, + reason="Unknown security patch version for Qt 6.11 so far", + ), +) + + @pytest.mark.usefixtures('reduce_args') class TestWebEngineArgs: @@ -190,6 +199,40 @@ class TestWebEngineArgs: args = qtargs.qt_args(parsed) assert ('--disable-accelerated-2d-canvas' in args) == has_arg + @pytest.mark.parametrize( + "qt_version, qt6, value, has_arg", + [ + ("5.15.2", False, "auto", False), + # 6.8.5 is broken too, but commercial-only + ("6.10.0", True, "always", True), + ("6.10.0", True, "auto", False), + ("6.10.1", True, "auto", True), + ("6.10.1", True, "never", False), + ("6.10.2", True, "always", True), + ("6.10.2", True, "auto", False), + pytest.param("6.11.0", True, "always", True, marks=_XFAIL_FUTURE_QT), + pytest.param("6.11.0", True, "auto", False, marks=_XFAIL_FUTURE_QT), + ], + ) + def test_disable_accessibility( + self, + parser, + version_patcher, + config_stub, + monkeypatch, + qt_version, + qt6, + value, + has_arg, + ): + version_patcher(qt_version) + config_stub.val.qt.workarounds.disable_accessibility = value + monkeypatch.setattr(machinery, 'IS_QT6', qt6) + + parsed = parser.parse_args([]) + args = qtargs.qt_args(parsed) + assert ('--disable-renderer-accessibility' in args) == has_arg + @pytest.mark.parametrize('flags, args', [ ([], []), (['--debug-flag', 'chromium'], ['--enable-logging', '--v=1']),