Describe the bug
Printing 45 VARIATION SELECTOR-16 characters after an emoji causes stack buffer overflow in encode_utf8
To Reproduce
Steps to reproduce the behavior:
- Run kitty
- Run
python3 -c 'print("\N{HEAVY EXCLAMATION MARK SYMBOL}" + 45 * "\N{VARIATION SELECTOR-16}")'
- Observe the crash.
Environment details
Linux framework 6.12.10-arch1-1 #1 SMP PREEMPT_DYNAMIC Sat, 18 Jan 2025 02:26:57 +0000 x86_64
S{PRETTY_NAME} 6.12.10-arch1-1 (/dev/tty)
DISTRIB_ID="Arch"
DISTRIB_RELEASE="rolling"
DISTRIB_DESCRIPTION="Arch Linux"
Running under: Wayland (sway version 1.10) missing: blur
OpenGL: '4.6 (Core Profile) Mesa 24.3.3-arch1.2' Detected version: 4.6
Frozen: False
Fonts:
medium: NotoSansMono-Regular: /usr/share/fonts/noto/NotoSansMono-Regular.ttf:0
Features: ()
bold: NotoSansMono-Bold: /usr/share/fonts/noto/NotoSansMono-Bold.ttf:0
Features: ()
italic: NotoSansMono-Regular: /usr/share/fonts/noto/NotoSansMono-Regular.ttf:0
Features: ()
bi: NotoSansMono-Bold: /usr/share/fonts/noto/NotoSansMono-Bold.ttf:0
Features: ()
Paths:
kitty: /home/stepan/tmp/kitty/kitty/launcher/kitty
base dir: /home/stepan/tmp/kitty
extensions dir: /home/stepan/tmp/kitty/kitty
system shell: /bin/bash
System color scheme: no_preference. Applied color theme type: none
Config options different from defaults:
Important environment variables seen by the kitty process:
PATH /home/stepan/tmp/kitty/kitty/launcher:/home/stepan/.pyenv/shims:/home/stepan/.local/bin:/home/stepan/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl:/home/stepan/.local/bin:/home/stepan/.local/bin
LANG en_US.UTF-8
EDITOR nvim
SHELL /bin/bash
DISPLAY :0
WAYLAND_DISPLAY wayland-1
USER stepan
XCURSOR_SIZE 24
XDG_DATA_HOME /home/stepan/.local/share
XDG_CONFIG_HOME /home/stepan/.config
XDG_SEAT seat0
XDG_SESSION_TYPE wayland
XDG_DOWNLOAD_DIR /home/stepan/tmp
XDG_CACHE_HOME /home/stepan/.cache
XDG_SESSION_CLASS user
XDG_DESKTOP_DIR /home/stepan/tmp
XDG_VTNR 1
XDG_SESSION_ID 1
XDG_STATE_HOME /home/stepan/.local/state
XDG_RUNTIME_DIR /run/user/1000
Additional context
"\N{NAME OF THE CHARACTER}" is the pythonic way of getting a Unicode character by its name.
VARIATION SELECTOR-16 is used to hint the renderer to render the emoji in the emoji variant (meaning "❗️" rather than "❗︎").
Using it multiple times in a row is surely against the Unicode spec but kitty should not crash.
Running with sanitizers I get:
=================================================================
==125315==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ae4804bd560 at pc 0x7ae47c4a0d7c bp 0x7ffe0671e050 sp 0x7ffe0671e040
WRITE of size 1 at 0x7ae4804bd560 thread T0
#0 0x7ae47c4a0d7b in encode_utf8 kitty/charsets.c:242
#1 0x7ae47c573e9e in chars_as_utf8 kitty/fonts.c:671
#2 0x7ae47c5741f1 in fallback_font kitty/fonts.c:685
#3 0x7ae47c574d5d in font_for_cell kitty/fonts.c:756
#4 0x7ae47c57a7b1 in render_line kitty/fonts.c:1839
#5 0x7ae47c70e67c in screen_update_cell_data kitty/screen.c:3274
#6 0x7ae47c72c37c in cell_prepare_to_render kitty/shaders.c:510
#7 0x7ae47c7390d1 in send_cell_data_to_gpu kitty/shaders.c:1064
#8 0x7ae47c4aaed1 in prepare_to_render_os_window kitty/child-monitor.c:784
#9 0x7ae47c4bd170 in render_os_window kitty/child-monitor.c:881
#10 0x7ae47c4bdaf2 in render kitty/child-monitor.c:908
#11 0x7ae47c4bdca4 in process_global_state kitty/child-monitor.c:1291
#12 0x7ae47c4bddb7 in do_state_check kitty/child-monitor.c:1272
#13 0x7ae474f60b26 in dispatchTimers glfw/backend_utils.c:208
#14 0x7ae474f613b6 in pollForEvents glfw/backend_utils.c:309
#15 0x7ae474f11fe0 in handleEvents glfw/wl_window.c:1248
#16 0x7ae474f209f3 in _glfwPlatformWaitEvents glfw/wl_window.c:1790
#17 0x7ae474f07d82 in _glfwPlatformRunMainLoop glfw/main_loop.h:30
#18 0x7ae474ee30f9 in glfwRunMainLoop glfw/init.c:360
#19 0x7ae47c5e6a55 in run_main_loop kitty/glfw.c:2195
#20 0x7ae47c4a1551 in main_loop kitty/child-monitor.c:1316
#21 0x7ae48326f9e6 in method_vectorcall_NOARGS Objects/descrobject.c:454
#22 0x7ae483167bf9 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:92
#23 0x7ae4832f8b9c in PyObject_Vectorcall Objects/call.c:325
#24 0x7ae4832f8b9c in _PyEval_EvalFrameDefault Python/bytecodes.c:2706
#25 0x7ae483270756 in _PyObject_FastCallDictTstate Objects/call.c:133
#26 0x7ae483288e39 in _PyObject_Call_Prepend Objects/call.c:508
#27 0x7ae483288e39 in slot_tp_call Objects/typeobject.c:8770
#28 0x7ae483270641 in _PyObject_MakeTpCall Objects/call.c:240
#29 0x7ae4832f8b9c in PyObject_Vectorcall Objects/call.c:325
#30 0x7ae4832f8b9c in _PyEval_EvalFrameDefault Python/bytecodes.c:2706
#31 0x7ae48330820b in _PyEval_EvalFrame Include/internal/pycore_ceval.h:89
#32 0x7ae48330820b in _PyEval_Vector Python/ceval.c:1683
#33 0x7ae48330820b in PyEval_EvalCode Python/ceval.c:578
#34 0x7ae48339e252 in builtin_exec_impl.isra.27 Python/bltinmodule.c:1096
#35 0x7ae48339e252 in builtin_exec Python/clinic/bltinmodule.c.h:586
#36 0x7ae48323d3c3 in cfunction_vectorcall_FASTCALL_KEYWORDS Objects/methodobject.c:438
#37 0x7ae483167bf9 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:92
#38 0x7ae4832f8b9c in PyObject_Vectorcall Objects/call.c:325
#39 0x7ae4832f8b9c in _PyEval_EvalFrameDefault Python/bytecodes.c:2706
#40 0x7ae48327bcc7 in _PyVectorcall_Call Objects/call.c:271
#41 0x7ae48327bcc7 in _PyObject_Call Objects/call.c:354
#42 0x7ae48339494d in pymain_run_module Modules/main.c:300
#43 0x7ae4831ff91f in pymain_run_python Modules/main.c:626
#44 0x7ae4831ff91f in Py_RunMain Modules/main.c:709
#45 0x5888c9555049 in run_embedded kitty/launcher/main.c:217
#46 0x5888c9557fe8 in main kitty/launcher/main.c:467
#47 0x7ae482634e07 (/usr/lib/libc.so.6+0x25e07) (BuildId: 98b3d8e0b8c534c769cb871c438b4f8f3a8e4bf3)
#48 0x7ae482634ecb in __libc_start_main (/usr/lib/libc.so.6+0x25ecb) (BuildId: 98b3d8e0b8c534c769cb871c438b4f8f3a8e4bf3)
#49 0x5888c95516d4 in _start (/home/stepan/tmp/kitty/kitty/launcher/kitty+0x136d4) (BuildId: 2cf0ae18c01e6b24941e1965bc1714fb7fe9317c)
Address 0x7ae4804bd560 is located in stack of thread T0 at offset 352 in frame
#0 0x7ae47c573fe5 in fallback_font kitty/fonts.c:678
This frame has 4 object(s):
[32, 64) 'fi' (line 686)
[96, 128) 'itr' (line 678)
[160, 192) 'itr'
[224, 352) 'cell_text' (line 684) <== Memory access at offset 352 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow kitty/charsets.c:242 in encode_utf8
Shadow bytes around the buggy address:
0x7ae4804bd280: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
0x7ae4804bd300: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
0x7ae4804bd380: f5 f5 f5 f5 00 00 00 00 00 00 00 00 00 00 00 00
0x7ae4804bd400: f1 f1 f1 f1 00 00 00 00 f2 f2 f2 f2 00 00 00 00
0x7ae4804bd480: f2 f2 f2 f2 00 00 00 00 f2 f2 f2 f2 00 00 00 00
=>0x7ae4804bd500: 00 00 00 00 00 00 00 00 00 00 00 00[f3]f3 f3 f3
0x7ae4804bd580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7ae4804bd600: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7ae4804bd680: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7ae4804bd700: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7ae4804bd780: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==125315==ABORTING
This has been originally found by @nicki-krizek and minimized by me.
Describe the bug
Printing 45
VARIATION SELECTOR-16characters after an emoji causes stack buffer overflow inencode_utf8To Reproduce
Steps to reproduce the behavior:
python3 -c 'print("\N{HEAVY EXCLAMATION MARK SYMBOL}" + 45 * "\N{VARIATION SELECTOR-16}")'Environment details
Additional context
"\N{NAME OF THE CHARACTER}"is the pythonic way of getting a Unicode character by its name.VARIATION SELECTOR-16is used to hint the renderer to render the emoji in the emoji variant (meaning "❗️" rather than "❗︎").Using it multiple times in a row is surely against the Unicode spec but
kittyshould not crash.Running with sanitizers I get:
This has been originally found by @nicki-krizek and minimized by me.