diff --git a/flake.nix b/flake.nix index 1e7bd56..a0ba69c 100644 --- a/flake.nix +++ b/flake.nix @@ -89,21 +89,19 @@ docs = pkgs.callPackage ./nix/docs.nix { inherit self; }; default = nova-shell; - # Reproducer wrappers: run test/screen-uaf-reproducer/shell.qml - # with patched vs unpatched quickshell to confirm the fix. - screen-uaf-reproducer-patched = pkgs.writeShellScriptBin "screen-uaf-reproducer-patched" '' - exec ${qs}/bin/quickshell -p ${./test/screen-uaf-reproducer/shell.qml} - ''; - screen-uaf-reproducer-unpatched = + # nova-shell on unpatched Qt for A/B crash testing + nova-shell-unpatched = let qsUnpatched = (rawPkgs.extend quickshell.overlays.default).quickshell.override { withX11 = false; withI3 = false; }; in - rawPkgs.writeShellScriptBin "screen-uaf-reproducer-unpatched" '' - exec ${qsUnpatched}/bin/quickshell -p ${./test/screen-uaf-reproducer/shell.qml} - ''; + rawPkgs.callPackage ./nix/package.nix { + quickshell = qsUnpatched; + nova-stats = rawPkgs.callPackage ./nix/stats-daemon.nix { }; + nova-shaders = rawPkgs.callPackage ./nix/shaders.nix { }; + }; } ); diff --git a/test/screen-uaf-reproducer/shell.qml b/test/screen-uaf-reproducer/shell.qml deleted file mode 100644 index 5ec71d1..0000000 --- a/test/screen-uaf-reproducer/shell.qml +++ /dev/null @@ -1,52 +0,0 @@ -// Minimal reproducer for Qt 6 Wayland screen use-after-free (QTBUG-XXXXXX). -// -// Creates many layer-shell surfaces bound to each screen. When an output is -// removed, the compositor sends wl_surface.leave + wl_registry.global_remove -// in the same event batch. libwayland resolves the wl_output proxy pointer at -// demarshal time; if the global_remove handler destroys the proxy first, the -// surface.leave handler receives a dangling pointer and crashes in -// QWaylandScreen::fromWlOutput / QPlatformScreen::screen(). -// -// Run with unpatched Qt 6.10.2: -// quickshell -p ./shell.qml -// -// Then toggle an output: -// niri msg action power-off-monitors (move mouse to wake) -// wlr-randr --output eDP-1 --off && sleep 0.3 && wlr-randr --output eDP-1 --on -// or unplug/replug an external monitor -// -// Should crash within a few seconds of the output toggle. - -import Quickshell -import Quickshell.Wayland -import QtQuick - -ShellRoot { - // 20 layer-shell surfaces per screen - all bound to the output, - // so the compositor must send enter/leave for each on removal. - Variants { - model: Quickshell.screens - - Scope { - required property var modelData - - Repeater { - model: 20 - - PanelWindow { - screen: modelData - anchors { - top: true - left: true - } - width: 60 - height: 20 - margins.top: index * 22 - margins.left: 4 - exclusiveZone: 0 - color: "#80ff00ff" - } - } - } - } -} diff --git a/test/screen-uaf-reproducer/trigger.sh b/test/screen-uaf-reproducer/trigger.sh deleted file mode 100755 index 3137cf8..0000000 --- a/test/screen-uaf-reproducer/trigger.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env bash -# Trigger rapid output power-cycling to provoke the Qt Wayland screen UAF. -# -# First, in another terminal: -# nix run .#screen-uaf-reproducer-unpatched (should crash) -# nix run .#screen-uaf-reproducer-patched (should survive) -# -# Then run this script to toggle the output. -# -# Usage: ./trigger.sh [iterations] -# iterations: number of off/on cycles (default 20) - -set -euo pipefail - -cycles="${1:-20}" - -if command -v niri &>/dev/null && niri msg version &>/dev/null; then - echo "Detected Niri - using niri msg" - for i in $(seq 1 "$cycles"); do - echo "cycle $i/$cycles" - niri msg action power-off-monitors - sleep 0.3 - niri msg action power-on-monitors - sleep 0.5 - done -elif command -v wlr-randr &>/dev/null; then - output=$(wlr-randr --json 2>/dev/null | python3 -c \ - "import sys,json; print(next(o['name'] for o in json.load(sys.stdin) if o['enabled']))" 2>/dev/null \ - || wlr-randr | grep -oP '^\S+' | head -1) - if [ -z "$output" ]; then - echo "error: could not detect an output via wlr-randr" >&2 - exit 1 - fi - echo "Detected wlroots compositor - toggling output $output" - for i in $(seq 1 "$cycles"); do - echo "cycle $i/$cycles" - wlr-randr --output "$output" --off - sleep 0.3 - wlr-randr --output "$output" --on - sleep 0.5 - done -else - echo "error: neither niri nor wlr-randr found" >&2 - echo "Manually unplug/replug a monitor while the reproducer is running." >&2 - exit 1 -fi - -echo "Done. If the reproducer is still alive, the bug did not trigger." -echo "Try increasing iterations or adding more surfaces."