[Linux] DEBUG_PRINT_LAYOUT is left on in fl_keyboard_manager.cc; its loop looks up keycodes 0-7 and crashes on an X display without XKB (ssh -X)

未关闭 适合新手
#195,591 1 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 1 天内回复

还没有人认领这个 Issue。

评估

难度
2/5
预计耗时
1-3 小时
新手友好度
75/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
活跃
技术栈
c
领域
backend, desktop

调研方向

阅读 engine/src/flutter/shell/platform/linux/fl_keyboard_manager.cc,尤其是 DEBUG_PRINT_LAYOUT 的定义和 issue 中描述的 guarantee_layout() 循环。按照提供的步骤,在不受信任的 X 显示环境中重现问题,然后检查禁用调试循环或将其设为可选后,首次按键是否不再导致崩溃。

由索引模型根据 Issue 内容生成。

描述

waiting for response
Steps to reproduce

On Linux, a Flutter app segfaults on its first key press when it runs as an untrusted X client, for example over ssh -X with OpenSSH's default ForwardX11Trusted no (the default on macOS). The same app works as a trusted client (ssh -Y).

Minimal repro on Ubuntu 22.04 or 24.04, Flutter 3.47.7 stable:

  1. flutter create --platforms=linux app
  2. In linux/runner/my_application.cc, call fl_dart_project_set_enable_impeller(project, FALSE); (so the software renderer works under Xvfb).
  3. flutter build linux --release
  4. Start an X server with the SECURITY extension and make an untrusted cookie:
    xauth -f t add :77 . $(mcookie)
    Xvfb :77 -auth t +extension SECURITY -noreset &
    XAUTHORITY=t xauth -f u generate :77 . untrusted timeout 3600
    
  5. Run the app as the untrusted client and type one key as a trusted one:
    DISPLAY=:77 XAUTHORITY=u FLUTTER_LINUX_RENDERER=software build/linux/x64/release/bundle/app &
    DISPLAY=:77 XAUTHORITY=t xdotool search --sync --onlyvisible --name app windowfocus --sync
    DISPLAY=:77 XAUTHORITY=t xdotool type a
    
Expected results

The key press reaches the app, as it does with XAUTHORITY=t (a trusted client).

Actual results

The app is killed by SIGSEGV in gdk_x11_keymap_lookup_key.

Cause: engine/src/flutter/shell/platform/linux/fl_keyboard_manager.cc line 19 has #define DEBUG_PRINT_LAYOUT, which has been on since flutter/engine#32665 (April 2022) and is still on in master. With it on, guarantee_layout() runs for (uint16_t keycode = 0; keycode < 128; keycode += 1), calling convert_key_to_char and so gdk_keymap_lookup_key() for keycodes 0 to 127 on the first key press of each group. It builds debug_layout_data, which is never printed.

X keycodes start at the display's min_keycode (8 here). With XKEYBOARD, GDK tolerates keycode 0. An untrusted client is not given XKEYBOARD, so GDK uses the core keymap, computes (0 - min_keycode) unsigned, and reads out of bounds.

Suggested fix: remove the #define (or make it opt-in). Optionally, convert_key_to_char could also skip keycodes outside the display's XDisplayKeycodes range.

Code sample

The stock flutter create app, with only the Impeller change in step 2.

Logs

Stack, Ubuntu 24.04, GTK 3.24.41-4ubuntu1.3, gdb with debuginfod:

#0  gdk_x11_keymap_lookup_key (keymap=GdkX11Keymap, key=0x7fffffffc840) at gdk/x11/gdkkeys-x11.c:1063
#1  libflutter_linux_gtk.so (guarantee_layout / convert_key_to_char, inlined)
#2  libflutter_linux_gtk.so (fl_keyboard_manager_handle_event path)
#3-#7  g_signal_emit key-press-event on FlView
#8  gtk_widget_event_internal (FlView)
#9  gtk_window_propagate_key_event
#10 gtk_window_key_press_event
#16-#19 gtk_widget_event_internal / propagate_event / gtk_main_do_event
#21 _gdk_event_emit
#23 gdk_event_source_dispatch
#24-#28 g_main_context_iteration / g_application_run
#29 main

At the crash: *key = {keycode = 0, group = 0, level = 0}, keymap min_keycode = 8, max_keycode = 255, keysyms_per_keycode = 7, xkb_desc = NULL, rax = 0xffffffc8 (that is (0 - 8) * 7). A breakpoint on gdk_keymap_lookup_key counts 354 calls on the first key: keycodes 0 to 127 at levels 0 and 1 (the debug loop) plus the 49 layout goals. The same crash happens on Ubuntu 22.04 (GTK 3.24.33).

Flutter Doctor output

Flutter 3.47.7 stable, engine d8a2d6c768, on Ubuntu 22.04 and 24.04 (GitHub Actions runners).

主要语言
Dart
星标
181k
派生
33.3k
平均合并
1 天 19 小时
30 天内合并 PR
283

环境准备

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

flutter/flutter 的其他 Issue

查看 flutter/flutter 的全部 Issue

相似的 Issue

更多 Dart Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。