Skip to content

[Linux] Deterministic SIGSEGV inside libfontconfig when SkFontMgr_fontconfig resolves a styled CJK match (Deepin 25 / fontconfig 2.17.1) #357

Description

@X-SCI-TECH

Reported on the advice of v2rayN maintainers during review of v2rayN PR #10115 — they pointed at src/ports/SkFontMgr_fontconfig.cpp as the right place for this.

Related: v2rayN issue #10112, rejected workaround PR #10115.

Summary

The Avalonia/SkiaSharp application v2rayN 7.24.9 crashes with a deterministic SIGSEGV about 13–14 seconds after startup on Deepin 25 (X11, LANG=zh_CN.UTF-8), whenever the app renders CJK text that goes through the system-wide fontconfig rule set of the distribution.

The fault is an out-of-bounds read executed inside libfontconfig.so.1.16.1 (FcFontMatch / font-prepare path) during a CJK font match request issued from libSkiaSharp.so (this SkFontMgr_fontconfig port). No managed exception is reported before the crash; the app simply segfaults in native code.

Environment

  • OS: Deepin 25 "crimson", kernel 6.18.36, X11 (KWin/DDE), HiDPI 2736×1824, Xft.dpi=192
  • glibc: 2.38-6deepin27
  • fontconfig: 2.17.1-5 (libfontconfig.so.1.16.1)
  • libfreetype: 2.13.2+dfsg-1deepin2
  • Application: v2rayN 7.24.9, self-contained .NET, Avalonia 11.x on SkiaSharp (Linux)
  • Fonts (552 families installed): SourceHanSansSC-Regular/Medium.otf (family "Source Han Sans SC"/"思源黑体" — Regular only, no Bold/Italic), NotoSansCJK-{Regular,Bold}.ttc, NotoSerifCJK-{Regular,Bold}.ttc, wqy microhei/zenhei
  • Deepin fontconfig conf.d: 62 rule files, including 55-deepin-default, 55-language-deepin-*, 60-generic, 65-nonlatin, 70-no-bitmaps, 90-synthetic

Crash evidence (core dump)

  • SIG=11, sig_code=1 (SEGV_MAPERR), faulting read address 0x75f377fe2000
  • 25 threads; only the main thread truly faulted, all others parked in futex
  • Register snapshot of the faulting frame:
RIP=libc.so.6+0x130646  (AVX memcpy loop)
RAX=0x75f3f7400058  RDI=0x75f3f8245000 (dst)  RSI=0x75f377fdefa8 (src)
RDX=0x1140 (len = 4416 bytes)  RSP=0x7ffe96d14378
  • Stack modules near the crash: libc memcpy ← libfontconfig.so.1.16.1 (FcFontMatch/font-prepare) ← libSkiaSharp.so ← Avalonia.Controls.dll (managed frames compiled by coreclr JIT)

i.e. Skia asked fontconfig to resolve/match a font for CJK text, and fontconfig crashed while copying pattern data — an out-of-bounds read from a heap region inside memcpy.

Trigger / reproduction

  1. Install v2rayN 7.24.9 official Linux .deb on Deepin 25 (X11, Chinese locale).
  2. Launch; no servers or subscriptions needed. The main window opens and works for ~13 s.
  3. Crash happens deterministically at the first UI refresh that renders styled CJK text (timing correlates with the auto update-check HTTP timeout → UI text update).
  4. fc-list / fc-match on the same machine do not crash, and the same fonts render fine in Qt/DTK applications → the failure is fontconfig-internal during a match triggered from Skia's font manager.

Controlled experiments (all on the affected machine)

Config Result
System fontconfig, all Deepin rules + CJK fonts crash ~13–14 s (6+ reproductions)
Same font dirs, no rule files (<dir> only) stable
Full rules, but Source Han Sans → DejaVu Sans (no CJK rendering at all) stable
Full rules, Source Han → Noto Sans CJK SC (CJK still rendered) crash
Full rules minus 90-synthetic.conf still crash
Minimal rules + CJK fonts, default family Noto Sans CJK SC stable (hours)

Findings:

  • Removing the synthetic-styles rule alone is not sufficient → not (only) the 90-synthetic.conf embolden/oblique path.
  • The crash requires a combination of the Deepin rule set and actual CJK glyph resolution; it does not follow any single rule file (simple bisect inconclusive).
  • It is not a font-file problem: identical files work in other toolkits.
  • Most likely trigger: Skia requests a styled CJK match (e.g. bold/oblique variants that do not exist for Source Han Sans SC, or lang=zh fallback) and fontconfig's pattern-copy code reads out of bounds while the Deepin rule set is active.

Questions for mono/skia

  1. Is there a known issue with this SkFontMgr_fontconfig port when requesting styled CJK fonts against rule sets that rely on synthetic faces? The fault is inside fontconfig itself, but it is Skia that drives the FcFontMatch call from the UI thread.
  2. Does this port ever reuse/free FcPatterns in a way that could feed corrupt patterns to fontconfig (pattern lifecycle bug on the Skia side)?
  3. Would it be acceptable to harden the GL/FontMgr path (e.g. fall back to a per-app minimal fontconfig, or avoid style synthesis requests) until the underlying fontconfig bug is fixed upstream? (Cross-reference the fontconfig report at https://gitlab.freedesktop.org/fontconfig/fontconfig)

Willing to provide

  • Full core dump (747 MB) and complete guiLogs on request.
  • Any additional env info or instrumented builds (e.g. FONTCONFIG_DEBUG=1 output, or an ASan build of Skia) needed to pin down whether Skia or fontconfig is at fault.

Note: this application-side workaround (v2rayN PR #10115, pointing FONTCONFIG_FILE at a minimal config) was not merged; the maintainers agreed the correct place to fix is upstream — hence this report.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions