gpui: Bump resvg/usvg and regression test for panic (#59704)

Bumps resvg and usvg to fix a panic when rendering some complex mermaid
diagrams.

Closes FR-90

---

Release Notes:

- N/A or Added/Fixed/Improved ...
This commit is contained in:
Cameron Mcloughlin 2026-06-22 16:42:12 +01:00 committed by GitHub
parent 50b4a1c17e
commit f791aa57d7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 103 additions and 55 deletions

91
Cargo.lock generated
View file

@ -6754,7 +6754,7 @@ version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbc773e24e02d4ddd8395fd30dc147524273a83e54e0f312d986ea30de5f5646"
dependencies = [
"roxmltree",
"roxmltree 0.20.0",
]
[[package]]
@ -7259,16 +7259,6 @@ dependencies = [
"syn 2.0.117",
]
[[package]]
name = "gif"
version = "0.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ae047235e33e2829703574b54fdec96bfbad892062d97fed2f76022287de61b"
dependencies = [
"color_quant",
"weezl",
]
[[package]]
name = "gif"
version = "0.14.2"
@ -8918,7 +8908,7 @@ dependencies = [
"byteorder-lite",
"color_quant",
"exr",
"gif 0.14.2",
"gif",
"image-webp",
"moxcms",
"num-traits",
@ -8928,8 +8918,8 @@ dependencies = [
"rayon",
"rgb",
"tiff",
"zune-core 0.5.1",
"zune-jpeg 0.5.15",
"zune-core",
"zune-jpeg",
]
[[package]]
@ -8964,9 +8954,9 @@ dependencies = [
[[package]]
name = "imagesize"
version = "0.13.0"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edcd27d72f2f071c64249075f42e205ff93c9a4c5f6c6da53e79ed9f9832c285"
checksum = "09e54e57b4c48b40f7aec75635392b12b3421fa26fe8b4332e63138ed278459c"
[[package]]
name = "imara-diff"
@ -9590,12 +9580,13 @@ dependencies = [
[[package]]
name = "kurbo"
version = "0.11.3"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c62026ae44756f8a599ba21140f350303d4f08dcdcc71b5ad9c9bb8128c13c62"
checksum = "4b60dfc32f652b926df6192e55525b16d186c69d47876c3ead4da5cc9f8450e2"
dependencies = [
"arrayvec",
"euclid",
"polycool",
"smallvec",
]
@ -10918,6 +10909,7 @@ dependencies = [
"merman",
"quick-xml 0.38.3",
"serde_json",
"usvg",
]
[[package]]
@ -13672,6 +13664,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3"
[[package]]
name = "polycool"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50596ddc09eb5ad5f75cacd40209568e66df71baf86e1499a0e99c4cff12a5a6"
dependencies = [
"arrayvec",
]
[[package]]
name = "pori"
version = "0.0.0"
@ -15337,19 +15338,19 @@ dependencies = [
[[package]]
name = "resvg"
version = "0.45.1"
version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8928798c0a55e03c9ca6c4c6846f76377427d2c1e1f7e6de3c06ae57942df43"
checksum = "b563218631706d614e23059436526d005b50ab5f2d506b55a17eb65c5eb83419"
dependencies = [
"gif 0.13.3",
"gif",
"image-webp",
"log",
"pico-args",
"rgb",
"svgtypes 0.15.3",
"svgtypes 0.16.1",
"tiny-skia",
"usvg",
"zune-jpeg 0.4.21",
"zune-jpeg",
]
[[package]]
@ -15492,6 +15493,15 @@ version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97"
[[package]]
name = "roxmltree"
version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1964b10c76125c36f8afe190065a4bf9a87bf324842c05701330bba9f1cacbb"
dependencies = [
"memchr",
]
[[package]]
name = "rpassword"
version = "7.5.2"
@ -17750,11 +17760,11 @@ dependencies = [
[[package]]
name = "svgtypes"
version = "0.15.3"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68c7541fff44b35860c1a7a47a7cadf3e4a304c457b58f9870d9706ece028afc"
checksum = "695b5790b3131dafa99b3bbfd25a216edb3d216dad9ca208d4657bfb8f2abc3d"
dependencies = [
"kurbo 0.11.3",
"kurbo 0.13.1",
"siphasher 1.0.1",
]
@ -18549,7 +18559,7 @@ dependencies = [
"half",
"quick-error 2.0.1",
"weezl",
"zune-jpeg 0.5.15",
"zune-jpeg",
]
[[package]]
@ -19774,24 +19784,24 @@ checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
[[package]]
name = "usvg"
version = "0.45.1"
version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80be9b06fbae3b8b303400ab20778c80bbaf338f563afe567cf3c9eea17b47ef"
checksum = "e419dff010bb12512b0ae9e3d2f318dfbdf0167fde7eb05465134d4e8756076f"
dependencies = [
"base64 0.22.1",
"data-url",
"flate2",
"fontdb",
"imagesize",
"kurbo 0.11.3",
"kurbo 0.13.1",
"log",
"pico-args",
"roxmltree",
"roxmltree 0.21.1",
"rustybuzz",
"simplecss",
"siphasher 1.0.1",
"strict-num",
"svgtypes 0.15.3",
"svgtypes 0.16.1",
"tiny-skia-path",
"unicode-bidi",
"unicode-script",
@ -23498,12 +23508,6 @@ dependencies = [
name = "ztracing_macro"
version = "0.1.0"
[[package]]
name = "zune-core"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a"
[[package]]
name = "zune-core"
version = "0.5.1"
@ -23519,22 +23523,13 @@ dependencies = [
"simd-adler32",
]
[[package]]
name = "zune-jpeg"
version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29ce2c8a9384ad323cf564b67da86e21d3cfdff87908bc1223ed5c99bc792713"
dependencies = [
"zune-core 0.4.12",
]
[[package]]
name = "zune-jpeg"
version = "0.5.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296"
dependencies = [
"zune-core 0.5.1",
"zune-core",
]
[[package]]

View file

@ -721,6 +721,12 @@ reqwest = { git = "https://github.com/zed-industries/reqwest.git", rev = "c15662
"socks",
"stream",
], package = "zed-reqwest", version = "0.12.15-zed" }
resvg = { version = "0.46.0", default-features = false, features = [
"text",
"system-fonts",
"memmap-fonts",
"raster-images",
] }
rsa = "0.9.6"
runtimelib = { version = "1.4.0", default-features = false, features = [
"async-dispatcher-runtime", "aws-lc-rs"
@ -813,6 +819,7 @@ unicode-width = "0.2"
unindent = "0.2.0"
url = "2.2"
urlencoding = "2.1.2"
usvg = { version = "0.46.0", default-features = false }
uuid = { version = "1.1.2", features = ["v4", "v5", "v7", "serde"] }
vte = { version = "0.15.0", features = ["ansi"] }
walkdir = "2.5"

View file

@ -79,13 +79,8 @@ raw-window-handle = "0.6"
regex.workspace = true
refineable.workspace = true
scheduler.workspace = true
resvg = { version = "0.45.0", default-features = false, features = [
"text",
"system-fonts",
"memmap-fonts",
"raster-images"
] }
usvg = { version = "0.45.0", default-features = false }
resvg.workspace = true
usvg.workspace = true
ttf-parser = "0.25"
util_macros.workspace = true
schemars.workspace = true

View file

@ -313,6 +313,31 @@ mod tests {
db
}
#[test]
fn text_with_split_glyph_clusters_in_mixed_fonts_does_not_panic() {
let mut db = Database::new();
db.load_font_data(IBM_PLEX_REGULAR.to_vec());
db.load_font_data(LILEX_REGULAR.to_vec());
let options = usvg::Options {
fontdb: std::sync::Arc::new(db),
..Default::default()
};
// A base letter followed by a stack of combining marks. Under HarfBuzz's
// default cluster merging every mark glyph shares the base's byte index,
// which is the "glyph splitting" condition that triggered the panic. The
// chunk must use two different fonts so the buggy merge path runs.
let zalgo = "e\u{0301}\u{0302}\u{0303}\u{0304}\u{0306}\u{0307}\u{0308}\u{030a}";
let svg = format!(
r#"<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg"><text font-family="Lilex" font-size="32">{zalgo}<tspan font-family="IBM Plex Sans">{zalgo}</tspan></text></svg>"#
);
// Before the fix this aborts via panic with a message like
// "removal index (is 5) should be < len (is 5)".
usvg::Tree::from_data(svg.as_bytes(), &options)
.expect("SVG with mixed-font text should parse");
}
#[test]
fn test_is_emoji_presentation() {
let cases = [

View file

@ -25,3 +25,4 @@ serde_json.workspace = true
[dev-dependencies]
gpui = { workspace = true, features = ["test-support"] }
mermaid_render = { path = ".", features = ["test-support"] }
usvg.workspace = true

View file

@ -185,6 +185,31 @@ pub fn render_to_svg(source: &str, theme: &MermaidTheme) -> Result<String> {
mod tests {
use super::*;
#[test]
fn mermaid_diagram_with_mixed_weight_combining_marks_does_not_panic() {
const IBM_PLEX_REGULAR: &[u8] =
include_bytes!("../../../assets/fonts/ibm-plex-sans/IBMPlexSans-Regular.ttf");
const IBM_PLEX_SEMIBOLD: &[u8] =
include_bytes!("../../../assets/fonts/ibm-plex-sans/IBMPlexSans-SemiBold.ttf");
let zalgo = "Ne\u{0301}\u{0302}\u{0303}\u{0304}\u{0306}\u{0307}\u{0308}\u{030a}d";
let source = format!("flowchart TD\n A[\"**{zalgo}** {zalgo}\"]");
let svg = render_to_svg(&source, &MermaidTheme::default())
.expect("mermaid diagram should render to SVG");
let mut db = usvg::fontdb::Database::new();
db.load_font_data(IBM_PLEX_REGULAR.to_vec());
db.load_font_data(IBM_PLEX_SEMIBOLD.to_vec());
db.set_sans_serif_family("IBM Plex Sans");
let options = usvg::Options {
fontdb: std::sync::Arc::new(db),
..Default::default()
};
usvg::Tree::from_data(svg.as_bytes(), &options)
.expect("rasterizing mermaid text should not panic");
}
/// An ER diagram whose attribute-block tokens begin with a multibyte
/// UTF-8 character (e.g. CJK type/field names) must not panic while the
/// lexer probes for the two-character `PK`/`FK`/`UK` keys.