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
- Install v2rayN 7.24.9 official Linux .deb on Deepin 25 (X11, Chinese locale).
- Launch; no servers or subscriptions needed. The main window opens and works for ~13 s.
- 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).
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
- 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.
- Does this port ever reuse/free
FcPatterns in a way that could feed corrupt patterns to fontconfig (pattern lifecycle bug on the Skia side)?
- 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.
Reported on the advice of v2rayN maintainers during review of v2rayN PR #10115 — they pointed at
src/ports/SkFontMgr_fontconfig.cppas 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
SIGSEGVabout 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 fromlibSkiaSharp.so(thisSkFontMgr_fontconfigport). No managed exception is reported before the crash; the app simply segfaults in native code.Environment
libfontconfig.so.1.16.1)SourceHanSansSC-Regular/Medium.otf(family "Source Han Sans SC"/"思源黑体" — Regular only, no Bold/Italic),NotoSansCJK-{Regular,Bold}.ttc,NotoSerifCJK-{Regular,Bold}.ttc, wqy microhei/zenheiconf.d: 62 rule files, including55-deepin-default,55-language-deepin-*,60-generic,65-nonlatin,70-no-bitmaps,90-syntheticCrash evidence (core dump)
SIG=11,sig_code=1 (SEGV_MAPERR), faulting read address0x75f377fe2000futexlibc 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
fc-list/fc-matchon 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)
<dir>only)90-synthetic.confNoto Sans CJK SCFindings:
90-synthetic.confembolden/oblique path.Source Han Sans SC, orlang=zhfallback) and fontconfig's pattern-copy code reads out of bounds while the Deepin rule set is active.Questions for mono/skia
SkFontMgr_fontconfigport 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 theFcFontMatchcall from the UI thread.FcPatterns in a way that could feed corrupt patterns to fontconfig (pattern lifecycle bug on the Skia side)?Willing to provide
FONTCONFIG_DEBUG=1output, 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_FILEat a minimal config) was not merged; the maintainers agreed the correct place to fix is upstream — hence this report.