Skip to content

Crash in TextRenderer.cpp:780 with SIGABRT and gdb backtrace #1778

@Marenz

Description

@Marenz

Contour Terminal version

0.6.2-master-3172d94b

Installer source

GitHub: Source code

Operating System

opensuse tumbleweed

Architecture

x86-64 / amd64

Other Software

No response

Steps to reproduce

Run Contour terminal and trigger rendering of specific glyphs that lead to the crash. Exact reproduction steps not fully determined, but crash happens in vtrasterizer::TextRenderer::createRasterizedGlyph when rendering text.

Expected Behavior

No crash

Actual Behavior

Contour crashes with SIGABRT in thread "QSGRenderThread" when rendering text. GDB log and backtrace:

[2025-08-07 17:06:57.299520] [vt.parser] Invalid VT sequence: CSI = 5 u
[2025-08-07 17:06:57.540112] [vt.parser] Unknown VT sequence: CSI > 4;0 m
[2025-08-07 17:06:57.540217] [vt.parser] Unknown VT sequence: CSI = u
[2025-08-07 17:06:57.541215] [vt.parser] Unknown VT sequence: CSI > 4;1 m
[2025-08-07 17:06:57.541304] [vt.parser] Invalid VT sequence: CSI = 5 u
[2025-08-07 17:06:57.777488] [vt.parser] Unknown VT sequence: OSC 133 C;cmdline_url=gemini
[2025-08-07 17:06:57.777599] [vt.parser] Unknown VT sequence: CSI > 4;0 m
[2025-08-07 17:06:57.777626] [vt.parser] Unknown VT sequence: CSI = u
[/home/marenz/repos/contour/src/vtrasterizer/TextRenderer.cpp:780] Precondition failed. 0 < pixelCount && static_cast<size_t>(pixelCount) <= glyph.bitmap.size()

Thread 45 "QSGRenderThread" received signal SIGABRT, Aborted.
[Switching to Thread 0x7fffacbff6c0 (LWP 42818)]
Downloading 4.48 K source file /usr/src/debug/glibc-2.41/nptl/pthread_kill.c
[##################################################################################################]                                                                                                      __pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0)
    at pthread_kill.c:44
44            return INTERNAL_SYSCALL_ERROR_P (ret) ? INTERNAL_SYSCALL_ERRNO (ret) : 0;
Missing separate debuginfos, use: zypper install libutempter0-debuginfo-1.2.1-2.2.x86_64 libharfbuzz0-debuginfo-11.3.2-1.1.x86_64 libstdc++6-debuginfo-15.1.1+git9973-1.1.x86_64 libgcc_s1-debuginfo-15.1.1+git9973-1.1.x86_64 libopenssl3-x86-64-v3-debuginfo-3.5.1-1.1.x86_64 libgomp1-debuginfo-15.1.1+git9973-1.1.x86_64 libeconf0-debuginfo-0.7.9-1.1.x86_64 Mesa-libGL1-debuginfo-25.1.6-420.1.x86_64 Mesa-dri-debuginfo-25.1.6-420.1.x86_64 libLLVM20-debuginfo-20.1.8-2.1.x86_64 libmpg123-0-debuginfo-1.33.0-1.1.x86_64 nvidia-compute-G06-debuginfo-570.172.08-37.1.x86_64 nvidia-gl-G06-debuginfo-570.172.08-37.1.x86_64 libvulkan_lvp-debuginfo-25.1.6-420.1.x86_64 Mesa-vulkan-device-select-debuginfo-25.1.6-420.1.x86_64 libheif1-debuginfo-1.20.1-1.1.x86_64 libheif-svtenc-debuginfo-1.20.1-1.1.x86_64 libheif-rav1e-debuginfo-1.20.1-1.1.x86_64 libheif-openjpeg-debuginfo-1.20.1-1.1.x86_64 libheif-jpeg-debuginfo-1.20.1-1.1.x86_64 libheif-ffmpeg-debuginfo-1.20.1-1.1.x86_64 libheif-dav1d-debuginfo-1.20.1-1.1.x86_64 libheif-aom-debuginfo-1.20.1-1.1.x86_64
(gdb) bt
#0  __pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0) at pthread_kill.c:44
#1  0x00007ffff469c6f3 in __pthread_kill_internal (threadid=<optimized out>, signo=6) at pthread_kill.c:89
#2  0x00007ffff4642106 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#3  0x00007ffff462938b in __GI_abort () at abort.c:73
#4  0x0000000000617047 in crispy::detail::fail
    (text="0 < pixelCount && static_cast<size_t>(pixelCount) <= glyph.bitmap.size()", message="Precondition failed.", file="/home/marenz/repos/contour/src/vtrasterizer/TextRenderer.cpp", line=780) at /home/marenz/repos/contour/src/crispy/assert.h:72
#5  0x00000000007b91f5 in vtrasterizer::TextRenderer::createRasterizedGlyph (this=this@entry=0x32e4350, tileLocation=...,
    tileLocation@entry=..., glyphKey=..., presentation=unicode::PresentationStyle::Text)
    at /home/marenz/repos/contour/src/vtrasterizer/TextRenderer.cpp:780
#6  0x00000000007ba13b in vtrasterizer::TextRenderer::createSlicedRasterizedGlyph (this=0x32e4350, tileLocation=...,
    tileLocation@entry=..., glyphKey=<optimized out>, presentation=<optimized out>, hash=...)
    at /home/marenz/repos/contour/src/vtrasterizer/TextRenderer.cpp:631
#7  0x00000000007bab35 in operator() (__closure=<synthetic pointer>, tileLocation=...)
    at /home/marenz/repos/contour/src/vtrasterizer/TextRenderer.cpp:619
#8  vtrasterizer::atlas::TextureAtlas<vtrasterizer::RenderTileAttributes>::constructTile<vtrasterizer::TextRenderer::getOrCreateRasterizedMetadata(const crispy::strong_hash&, const text::glyph_key&, unicode::PresentationStyle)::<lambda(vtrasterizer::atlas::TileLocation)> >
    (this=0x7fff84214ae0, createTileData=..., entryIndex=129) at /home/marenz/repos/contour/src/vtrasterizer/TextureAtlas.h:553
#9  operator() (__closure=<synthetic pointer>, entryIndex=129) at /home/marenz/repos/contour/src/vtrasterizer/TextureAtlas.h:598
#10 crispy::strong_lru_hashtable<vtrasterizer::atlas::TileAttributes<vtrasterizer::RenderTileAttributes> >::get_or_try_emplace<vtrasterizer::atlas::TextureAtlas<vtrasterizer::RenderTileAttributes>::get_or_try_emplace<vtrasterizer::TextRenderer::getOrCreateRasterizedMetadata(const crispy::strong_hash&, const text::glyph_key&, unicode::PresentationStyle)::<lambda(vtrasterizer::atlas::TileLocation)> >(const crispy::strong_hash&, vtrasterizer::TextRenderer::getOrCreateRasterizedMetadata(const crispy::strong_hash&, const text::glyph_key&, unicode::PresentationStyle)::<lambda(vtrasterizer::atlas::TileLocation)>)::<lambda(uint32_t)> >(const crispy::strong_hash &, struct {...})
    (this=0x7fff843777c0, hash=..., constructValue=...) at /home/marenz/repos/contour/src/crispy/StrongLRUHashtable.h:612
#11 0x00000000007bb02f in vtrasterizer::atlas::TextureAtlas<vtrasterizer::RenderTileAttributes>::get_or_try_emplace<vtrasterizer::TextRenderer::getOrCreateRasterizedMetadata(const crispy::strong_hash&, const text::glyph_key&, unicode::PresentationStyle)::<lambda(vtrasterizer::atlas::TileLocation)> > (this=<optimized out>, key=..., constructValue=...) at /home/marenz/repos/contour/src/vtrasterizer/TextureAtlas.h:596
#12 vtrasterizer::TextRenderer::getOrCreateRasterizedMetadata
    (this=0x32e4350, hash=..., glyphKey=<optimized out>, presentationStyle=<optimized out>)
    at /home/marenz/repos/contour/src/vtrasterizer/TextRenderer.cpp:614
#13 vtrasterizer::TextRenderer::renderTextGroup (this=0x32e4350, codepoints=Python Exception <class 'gdb.error'>: value has been optimized out

   , clusters=..., initialPenPosition=..., style=vtrasterizer::TextStyle::Regular, color=...)
    at /home/marenz/repos/contour/src/vtrasterizer/TextRenderer.cpp:578
#14 0x00000000007d1cc0 in vtrasterizer::TextClusterGrouper::flushTextClusterGroup (this=this@entry=0x32e4388)
    at /home/marenz/repos/contour/src/vtrasterizer/TextClusterGrouper.cpp:135
#15 0x00000000007d2137 in vtrasterizer::TextClusterGrouper::renderCell (this=<optimized out>, position=..., graphemeCluster=Python Exception <class 'gdb.error'>: value has been optimized out

   , style=<optimized out>, foregroundColor=...)
    at /home/marenz/repos/contour/src/vtrasterizer/TextClusterGrouper.cpp:90
#16 0x00000000007d231d in vtrasterizer::TextClusterGrouper::renderLine (this=0x32e4388, text=Python Exception <class 'gdb.error'>: value has been optimized out

   , lineOffset=..., foregroundColor=..., style=vtrasterizer::TextStyle::Regular)
    at /home/marenz/repos/contour/src/vtrasterizer/TextClusterGrouper.cpp:55
#17 0x00000000007b6a1a in vtrasterizer::TextRenderer::renderLine (this=<optimized out>, renderLine=<optimized out>)
    at /home/marenz/repos/contour/src/vtrasterizer/TextRenderer.cpp:434
#18 0x00000000007b22a6 in vtrasterizer::Renderer::renderLines (this=0x32e3ff0, renderableLines=<optimized out>)
    at /home/marenz/repos/contour/src/vtrasterizer/Renderer.cpp:348
#19 vtrasterizer::Renderer::render (this=0x32e3ff0, terminal=..., pressure=<optimized out>)
    at /home/marenz/repos/contour/src/vtrasterizer/Renderer.cpp:306
#20 0x00000000006f1ff3 in contour::display::TerminalDisplay::paint (this=0xc47320)
    at /home/marenz/repos/contour/src/contour/display/TerminalDisplay.cpp:719
#21 0x00000000006f206e in contour::display::TerminalDisplay::onAfterRendering (this=0xc47320)
    at /home/marenz/repos/contour/src/contour/display/TerminalDisplay.cpp:746
#22 0x00007ffff502fc48 in QtPrivate::QSlotObjectBase::call
    (this=<optimized out>, r=<optimized out>, a=0x7fffacbfe878, this=<optimized out>, r=<optimized out>, a=<optimized out>)
    at /usr/src/debug/qtbase-everywhere-src-6.9.1/src/corelib/kernel/qobjectdefs_impl.h:461
#23 doActivate<false> (sender=0xc63310, signal_index=29, argv=0x7fffacbfe878)
    at /usr/src/debug/qtbase-everywhere-src-6.9.1/src/corelib/kernel/qobject.cpp:4146
#24 0x00007ffff6d0acaf in QQuickWindowPrivate::renderSceneGraph (this=0xc63410)
    at /usr/src/debug/qtdeclarative-everywhere-src-6.9.1/src/quick/items/qquickwindow.cpp:692
#25 0x00007ffff6ee3a1f in QSGRenderThread::syncAndRender (this=<optimized out>)
    at /usr/src/debug/qtdeclarative-everywhere-src-6.9.1/src/quick/scenegraph/qsgthreadedrenderloop.cpp:762
#26 QSGRenderThread::run (this=0x7fffe4005780)
    at /usr/src/debug/qtdeclarative-everywhere-src-6.9.1/src/quick/scenegraph/qsgthreadedrenderloop.cpp:975
#27 0x00007ffff516611b in operator() (__closure=<optimized out>)
    at /usr/src/debug/qtbase-everywhere-src-6.9.1/src/corelib/thread/qthread_unix.cpp:434
#28 (anonymous namespace)::terminate_on_exception<QThreadPrivate::start(void*)::<lambda()> > (t=<optimized out>)
    at /usr/src/debug/qtbase-everywhere-src-6.9.1/src/corelib/thread/qthread_unix.cpp:366
#29 QThreadPrivate::start (arg=0x7fffe4005780) at /usr/src/debug/qtbase-everywhere-src-6.9.1/src/corelib/thread/qthread_unix.cpp:394
#30 0x00007ffff469a7be in start_thread (arg=<optimized out>) at pthread_create.c:448
#31 0x00007ffff471edcc in __GI___clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:78
(gdb) up
#1  0x00007ffff469c6f3 in __pthread_kill_internal (threadid=<optimized out>, signo=6) at pthread_kill.c:89
89        return __pthread_kill_implementation (threadid, signo, 0);
(gdb)
Downloading 1.07 K source file /usr/src/debug/glibc-2.41/signal/../sysdeps/posix/raise.c
#2  0x00007ffff4642106 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
26        int ret = __pthread_kill (__pthread_self (), sig);
(gdb)
Downloading 2.87 K source file /usr/src/debug/glibc-2.41/stdlib/abort.c
#3  0x00007ffff462938b in __GI_abort () at abort.c:73
73        raise (SIGABRT);
(gdb)
#4  0x0000000000617047 in crispy::detail::fail (text="0 < pixelCount && static_cast<size_t>(pixelCount) <= glyph.bitmap.size()",
    message="Precondition failed.", file="/home/marenz/repos/contour/src/vtrasterizer/TextRenderer.cpp", line=780)
    at /home/marenz/repos/contour/src/crispy/assert.h:72
72              std::abort();
(gdb)
#5  0x00000000007b91f5 in vtrasterizer::TextRenderer::createRasterizedGlyph (this=this@entry=0x32e4350, tileLocation=...,
    tileLocation@entry=..., glyphKey=..., presentation=unicode::PresentationStyle::Text)
    at /home/marenz/repos/contour/src/vtrasterizer/TextRenderer.cpp:780
780             Require(0 < pixelCount && static_cast<size_t>(pixelCount) <= glyph.bitmap.size());
(gdb) pixelCount
Undefined command: "pixelCount".  Try "help".
(gdb) print pixelCount
$1 = <optimized out>
(gdb) print glyph.bitmap.size()
^CQuit
(gdb) print glyph.bitmap
$2 = std::vector of length 352, capacity 352 = {0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000',
  0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000',
  0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000',
  0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000',
  0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000',
  0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 27 '\033', 35 '#', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000',
  0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 24 '\030', 217 '\331', 227 '\343', 35 '#', 0 '\000', 0 '\000', 0 '\000',
  0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 22 '\026', 214 '\326', 255 '\377', 255 '\377', 227 '\343',
  35 '#', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 19 '\023', 210 '\322', 255 '\377',
  255 '\377', 255 '\377', 255 '\377', 226 '\342', 35 '#', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 17 '\021',
  207 '\317', 255 '\377', 255 '\377', 218 '\332', 216 '\330', 252 '\374', 255 '\377', 226 '\342', 34 '"', 0 '\000', 0 '\000', 0 '\000',
  0 '\000', 0 '\000', 15 '\017', 203 '\313', 255 '\377', 241 '\361', 53 '5', 0 '\000', 0 '\000', 43 '+', 232 '\350', 255 '\377', 226 '\342',
  34 '"', 0 '\000', 0 '\000', 0 '\000', 13 '\r', 199 '\307', 255 '\377', 255 '\377', 178 '\262', 36 '$', 161 '\241', 183 '\267', 0 '\000',
  127 '\177', 255 '\377', 255 '\377', 226 '\342', 34 '"', 0 '\000', 11 '\v', 195 '\303', 255 '\377', 255 '\377', 255 '\377', 255 '\377',
  255 '\377', 255 '\377', 202 '\312', 0 '\000', 136 '\210', 255 '\377', 255 '\377', 255 '\377', 225 '\341', 34 '"', 38 '&', 235 '\353',
  255 '\377', 255 '\377', 255 '\377', 255 '\377', 255 '\377', 183 '\267'...}

Additional notes

See attached gdb log and backtrace for details. Crash appears to relate to precondition 0 < pixelCount && static_cast<size_t>(pixelCount) <= glyph.bitmap.size() failing in TextRenderer.cpp at line 780.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions