diff --git a/Cargo.lock b/Cargo.lock index 72a583dfb5..040e78679f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2953,7 +2953,7 @@ checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" [[package]] name = "typst" -version = "0.14.1" +version = "0.14.2" dependencies = [ "comemo", "ecow", @@ -2971,13 +2971,13 @@ dependencies = [ [[package]] name = "typst-assets" -version = "0.14.1" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98b250f6c1ddd0f435db2283c7eb36a9b72bee34d6397625bf7f817c64ad7c62" +checksum = "5613cb719a6222fe9b74027c3625d107767ec187bff26b8fc931cf58942c834f" [[package]] name = "typst-cli" -version = "0.14.1" +version = "0.14.2" dependencies = [ "chrono", "clap", @@ -3023,12 +3023,12 @@ dependencies = [ [[package]] name = "typst-dev-assets" -version = "0.14.1" -source = "git+https://github.com/typst/typst-dev-assets?tag=v0.14.1#03addcfb64f3f95209464a521e6aa49645bd271a" +version = "0.14.2" +source = "git+https://github.com/typst/typst-dev-assets?tag=v0.14.2#fe6cad916d8b20c20742512b2a3f3b247a2bc4f8" [[package]] name = "typst-docs" -version = "0.14.1" +version = "0.14.2" dependencies = [ "clap", "codex", @@ -3055,7 +3055,7 @@ dependencies = [ [[package]] name = "typst-eval" -version = "0.14.1" +version = "0.14.2" dependencies = [ "comemo", "ecow", @@ -3073,7 +3073,7 @@ dependencies = [ [[package]] name = "typst-fuzz" -version = "0.14.1" +version = "0.14.2" dependencies = [ "comemo", "libfuzzer-sys", @@ -3085,7 +3085,7 @@ dependencies = [ [[package]] name = "typst-html" -version = "0.14.1" +version = "0.14.2" dependencies = [ "bumpalo", "comemo", @@ -3104,7 +3104,7 @@ dependencies = [ [[package]] name = "typst-ide" -version = "0.14.1" +version = "0.14.2" dependencies = [ "comemo", "ecow", @@ -3121,7 +3121,7 @@ dependencies = [ [[package]] name = "typst-kit" -version = "0.14.1" +version = "0.14.2" dependencies = [ "dirs", "ecow", @@ -3145,7 +3145,7 @@ dependencies = [ [[package]] name = "typst-layout" -version = "0.14.1" +version = "0.14.2" dependencies = [ "az", "bumpalo", @@ -3179,7 +3179,7 @@ dependencies = [ [[package]] name = "typst-library" -version = "0.14.1" +version = "0.14.2" dependencies = [ "az", "bitflags 2.9.1", @@ -3244,7 +3244,7 @@ dependencies = [ [[package]] name = "typst-macros" -version = "0.14.1" +version = "0.14.2" dependencies = [ "heck", "proc-macro2", @@ -3254,7 +3254,7 @@ dependencies = [ [[package]] name = "typst-pdf" -version = "0.14.1" +version = "0.14.2" dependencies = [ "az", "bytemuck", @@ -3278,7 +3278,7 @@ dependencies = [ [[package]] name = "typst-realize" -version = "0.14.1" +version = "0.14.2" dependencies = [ "arrayvec", "bumpalo", @@ -3294,7 +3294,7 @@ dependencies = [ [[package]] name = "typst-render" -version = "0.14.1" +version = "0.14.2" dependencies = [ "bytemuck", "comemo", @@ -3312,7 +3312,7 @@ dependencies = [ [[package]] name = "typst-svg" -version = "0.14.1" +version = "0.14.2" dependencies = [ "base64", "comemo", @@ -3334,7 +3334,7 @@ dependencies = [ [[package]] name = "typst-syntax" -version = "0.14.1" +version = "0.14.2" dependencies = [ "ecow", "rustc-hash", @@ -3351,7 +3351,7 @@ dependencies = [ [[package]] name = "typst-tests" -version = "0.14.1" +version = "0.14.2" dependencies = [ "bitflags 2.9.1", "clap", @@ -3378,7 +3378,7 @@ dependencies = [ [[package]] name = "typst-timing" -version = "0.14.1" +version = "0.14.2" dependencies = [ "parking_lot", "serde", @@ -3388,7 +3388,7 @@ dependencies = [ [[package]] name = "typst-utils" -version = "0.14.1" +version = "0.14.2" dependencies = [ "once_cell", "portable-atomic", @@ -3700,9 +3700,9 @@ dependencies = [ [[package]] name = "wasmi" -version = "0.51.2" +version = "0.51.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "118030b2d125bc893e0cc5b1ce156eb41461f4373308cb5f2e3c698533b5e547" +checksum = "bb321403ce594274827657a908e13d1d9918aa02257b8bf8391949d9764023ff" dependencies = [ "spin", "wasmi_collections", @@ -3713,24 +3713,24 @@ dependencies = [ [[package]] name = "wasmi_collections" -version = "0.51.2" +version = "0.51.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "653fa20efc966818934524dceb54b1b81e6f845bbcc2e155d6e9fc32becf667e" +checksum = "e9b8e98e45a2a534489f8225e765cbf1cb9a3078072605e58158910cf4749172" [[package]] name = "wasmi_core" -version = "0.51.2" +version = "0.51.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65701f60308c7e46cca85f273ad17e80c60998cc63d3fa168ac393f62b123038" +checksum = "c25f375c0cdf14810eab07f532f61f14d4966f09c747a55067fdf3196e8512e6" dependencies = [ "libm", ] [[package]] name = "wasmi_ir" -version = "0.51.2" +version = "0.51.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6539f63bf2a6838f27876e2877f0b00a088e84f91e92445620cc6b977fde032" +checksum = "624e2a68a4293ecb8f564260b68394b29cf3b3edba6bce35532889a2cb33c3d9" dependencies = [ "wasmi_core", ] diff --git a/Cargo.toml b/Cargo.toml index 91712f246b..d662cda181 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ default-members = ["crates/typst-cli"] resolver = "2" [workspace.package] -version = "0.14.1" +version = "0.14.2" rust-version = "1.89" # also change in ci.yml authors = ["The Typst Project Developers"] edition = "2024" @@ -16,24 +16,24 @@ keywords = ["typst"] readme = "README.md" [workspace.dependencies] -typst = { path = "crates/typst", version = "0.14.1" } -typst-cli = { path = "crates/typst-cli", version = "0.14.1" } -typst-eval = { path = "crates/typst-eval", version = "0.14.1" } -typst-html = { path = "crates/typst-html", version = "0.14.1" } -typst-ide = { path = "crates/typst-ide", version = "0.14.1" } -typst-kit = { path = "crates/typst-kit", version = "0.14.1" } -typst-layout = { path = "crates/typst-layout", version = "0.14.1" } -typst-library = { path = "crates/typst-library", version = "0.14.1" } -typst-macros = { path = "crates/typst-macros", version = "0.14.1" } -typst-pdf = { path = "crates/typst-pdf", version = "0.14.1" } -typst-realize = { path = "crates/typst-realize", version = "0.14.1" } -typst-render = { path = "crates/typst-render", version = "0.14.1" } -typst-svg = { path = "crates/typst-svg", version = "0.14.1" } -typst-syntax = { path = "crates/typst-syntax", version = "0.14.1" } -typst-timing = { path = "crates/typst-timing", version = "0.14.1" } -typst-utils = { path = "crates/typst-utils", version = "0.14.1" } -typst-assets = "0.14.1" -typst-dev-assets = { git = "https://github.com/typst/typst-dev-assets", tag = "v0.14.1" } +typst = { path = "crates/typst", version = "0.14.2" } +typst-cli = { path = "crates/typst-cli", version = "0.14.2" } +typst-eval = { path = "crates/typst-eval", version = "0.14.2" } +typst-html = { path = "crates/typst-html", version = "0.14.2" } +typst-ide = { path = "crates/typst-ide", version = "0.14.2" } +typst-kit = { path = "crates/typst-kit", version = "0.14.2" } +typst-layout = { path = "crates/typst-layout", version = "0.14.2" } +typst-library = { path = "crates/typst-library", version = "0.14.2" } +typst-macros = { path = "crates/typst-macros", version = "0.14.2" } +typst-pdf = { path = "crates/typst-pdf", version = "0.14.2" } +typst-realize = { path = "crates/typst-realize", version = "0.14.2" } +typst-render = { path = "crates/typst-render", version = "0.14.2" } +typst-svg = { path = "crates/typst-svg", version = "0.14.2" } +typst-syntax = { path = "crates/typst-syntax", version = "0.14.2" } +typst-timing = { path = "crates/typst-timing", version = "0.14.2" } +typst-utils = { path = "crates/typst-utils", version = "0.14.2" } +typst-assets = "0.14.2" +typst-dev-assets = { git = "https://github.com/typst/typst-dev-assets", tag = "v0.14.2" } arrayvec = "0.7.4" az = "1.2" base64 = "0.22" @@ -141,7 +141,7 @@ ureq = { version = "2", default-features = false, features = ["native-tls", "gzi usvg = { version = "0.45", default-features = false, features = ["text"] } utf8_iter = "1.0.4" walkdir = "2" -wasmi = { version = "0.51.2", default-features = false, features = ["simd"] } +wasmi = { version = "0.51.5", default-features = false, features = ["simd"] } web-sys = "0.3" xmlparser = "0.13.5" xmlwriter = "0.1.0" diff --git a/crates/typst-library/src/foundations/array.rs b/crates/typst-library/src/foundations/array.rs index 0c2e2f5326..7dbe8e64bd 100644 --- a/crates/typst-library/src/foundations/array.rs +++ b/crates/typst-library/src/foundations/array.rs @@ -9,7 +9,9 @@ use serde::{Deserialize, Serialize}; use smallvec::SmallVec; use typst_syntax::{Span, Spanned}; -use crate::diag::{At, HintedStrResult, SourceDiagnostic, SourceResult, StrResult, bail}; +use crate::diag::{ + At, HintedStrResult, HintedString, SourceDiagnostic, SourceResult, StrResult, bail, +}; use crate::engine::Engine; use crate::foundations::{ Args, Bytes, CastInfo, Context, Dict, FromValue, Func, IntoValue, Reflect, Repr, Str, @@ -836,8 +838,9 @@ impl Array { /// Return a sorted version of this array, optionally by a given key /// function. The sorting algorithm used is stable. /// - /// Returns an error if two values could not be compared or if the key - /// or comparison function (if given) yields an error. + /// Returns an error if a pair of values selected for comparison could not + /// be compared, or if the key or comparison function (if given) yield an + /// error. /// /// To sort according to multiple criteria at once, e.g. in case of equality /// between some criteria, the key function can return an array. The results @@ -975,7 +978,18 @@ impl Array { match (key_of(a.clone()), key_of(b.clone())) { (Ok(a), Ok(b)) => ops::compare(&a, &b).unwrap_or_else(|err| { if result.is_ok() { - result = Err(err).at(span); + result = + Err(HintedString::from(err).with_hint(match key { + None => { + "consider choosing a `key` \ + or defining the comparison with `by`" + } + Some(_) => { + "consider defining the comparison with `by` \ + or choosing a different `key`" + } + })) + .at(span); } Ordering::Equal }), diff --git a/crates/typst-library/src/foundations/str.rs b/crates/typst-library/src/foundations/str.rs index fe1b3a7e83..05893b1303 100644 --- a/crates/typst-library/src/foundations/str.rs +++ b/crates/typst-library/src/foundations/str.rs @@ -58,8 +58,8 @@ pub use crate::__format_str as format_str; /// #"\"hello\n world\"!" \ /// #"1 2 3".split() \ /// #"1,2;3".split(regex("[,;]")) \ -/// #(regex("\d+") in "ten euros") \ -/// #(regex("\d+") in "10 euros") +/// #(regex("\\d+") in "ten euros") \ +/// #(regex("\\d+") in "10 euros") /// ``` /// /// # Escape sequences { #escapes } @@ -932,7 +932,7 @@ fn string_is_empty() -> EcoString { /// #"a,b;c".split(regex("[,;]")) /// /// // Works with show rules. -/// #show regex("\d+"): set text(red) +/// #show regex("\\d+"): set text(red) /// /// The numbers 1 to 10. /// ``` @@ -954,14 +954,18 @@ impl Regex { pub fn construct( /// The regular expression as a string. /// - /// Most regex escape sequences just work because they are not valid Typst - /// escape sequences. To produce regex escape sequences that are also valid in - /// Typst (e.g. `[\\]`), you need to escape twice. Thus, to match a verbatim - /// backslash, you would need to write `{regex("\\\\")}`. + /// Both Typst strings and regular expressions use backslashes for + /// escaping. To produce a regex escape sequence that is also valid in + /// Typst, you need to escape the backslash itself (e.g., writing + /// `{regex("\\\\")}` for the regex `\\`). Regex escape sequences that + /// are not valid Typst escape sequences (e.g., `\d` and `\b`) can be + /// entered into strings directly, but it's good practice to still + /// escape them to avoid ambiguity (i.e., `{regex("\\b\\d")}`). See the + /// [list of valid string escape sequences]($str/#escapes). /// /// If you need many escape sequences, you can also create a raw element /// and extract its text to use it for your regular expressions: - /// ```{regex(`\d+\.\d+\.\d+`.text)}```. + /// ``{regex(`\d+\.\d+\.\d+`.text)}``. regex: Spanned, ) -> SourceResult { Self::new(®ex.v).at(regex.span) diff --git a/crates/typst-library/src/loading/read.rs b/crates/typst-library/src/loading/read.rs index de7cb5b4fc..7221405afe 100644 --- a/crates/typst-library/src/loading/read.rs +++ b/crates/typst-library/src/loading/read.rs @@ -16,7 +16,7 @@ use crate::loading::{DataSource, Load, Readable}; /// ```example /// An example for a HTML file: \ /// #let text = read("example.html") -/// #raw(text, lang: "html") +/// #raw(text, block: true, lang: "html") /// /// Raw bytes: /// #read("tiger.jpg", encoding: none) diff --git a/docs/changelog/0.14.2.md b/docs/changelog/0.14.2.md new file mode 100644 index 0000000000..2f26258eb7 --- /dev/null +++ b/docs/changelog/0.14.2.md @@ -0,0 +1,19 @@ +--- +title: 0.14.2 +description: Changes in Typst 0.14.2 +--- + +# Version 0.14.2 (December 12, 2025) { #v0.14.2 } + +## Security +- Updated the WebAssembly runtime used for executing [plugins]($plugin). The version used in Typst 0.14.0 and 0.14.1 suffers from a memory handling vulnerability. Based on our investigation, the vulnerability would be very hard to exploit in practice, but an exploit could theoretically be feasible. In any case, **we recommend upgrading to Typst 0.14.2.** This holds in particular for local users. In the web app, the bug is not critical as the browser offers an extra layer of protection. + + Typst 0.13.1 and below are not affected by this vulnerability. + + _Technical details:_ The [`wasmi`](https://github.com/wasmi-labs/wasmi/) WebAssembly runtime versions used in 0.14.0 and 0.14.1 have a _use-after-free_ memory handling bug in certain memory growth situations. Specifically, the bug occurs when the plugin tries to grow its memory, but allocating the requested amount of memory fails. Based on our investigation, the bug is hard to trigger in practice as the WebAssembly linear memory is always limited to 4GB on a technical level and modern operating systems rarely fail to serve a 4GB memory allocation request (typically not even under RAM pressure). Once the bug is triggered, it would also still be very challenging to turn it into an actual exploit. Regardless, we recommend upgrading to Typst 0.14.2 for protection against a potential exploit. + +## Diagnostics +- Added a hint when [`array.sorted`]($array.sorted) fails because a pair of elements could not be compared. This hint aids with fixing bugs in user code that were surfaced by a change in internal sorting behavior in Typst 0.14.1. + +## Contributors + diff --git a/docs/changelog/welcome.md b/docs/changelog/welcome.md index befefbfc64..13cf94981d 100644 --- a/docs/changelog/welcome.md +++ b/docs/changelog/welcome.md @@ -7,6 +7,7 @@ description: | 最新のTypstリリースで追加された新機能を確認し、あなたのドキュメントをさらに進化させましょう。本セクションでは、Typstの最初の一般公開リリース以降に行われた全ての変更内容を記録しています。 ## Versions +- [Typst 0.14.2]($changelog/0.14.2) - [Typst 0.14.1]($changelog/0.14.1) - [Typst 0.14.0]($changelog/0.14.0) - [Typst 0.13.1]($changelog/0.13.1) diff --git a/docs/src/lib.rs b/docs/src/lib.rs index 0f8c97bc33..5941c5ee0d 100644 --- a/docs/src/lib.rs +++ b/docs/src/lib.rs @@ -224,6 +224,7 @@ fn changelog_pages(resolver: &dyn Resolver) -> PageModel { let base = format!("{}changelog/", resolver.base()); page.title = "変更履歴".into(); page.children = vec![ + md_page(resolver, &base, load!("changelog/0.14.2.md")), md_page(resolver, &base, load!("changelog/0.14.1.md")), md_page(resolver, &base, load!("changelog/0.14.0.md")), md_page(resolver, &base, load!("changelog/0.13.1.md")), diff --git a/tests/src/run.rs b/tests/src/run.rs index 70ee5bab9e..55bf2779ab 100644 --- a/tests/src/run.rs +++ b/tests/src/run.rs @@ -245,6 +245,12 @@ impl<'a> Runner<'a> { // Check hints. for hint in &diag.hints { + // HACK: This hint only gets emitted in debug builds, so filter it + // out to make the test suite also pass for release builds. + if hint == "set `RUST_BACKTRACE` to `1` or `full` to capture a backtrace" { + continue; + } + self.validate_note(NoteKind::Hint, diag.span.id(), range.clone(), hint); } } diff --git a/tests/suite/foundations/array.typ b/tests/suite/foundations/array.typ index 6558d687f4..7ab75dc11f 100644 --- a/tests/suite/foundations/array.typ +++ b/tests/suite/foundations/array.typ @@ -461,12 +461,19 @@ // Error: 32-37 cannot divide by zero #(1, 2, 0, 3).sorted(key: x => 5 / x) +--- array-sorted-underdetermined-with-key --- +// Error: 2-40 cannot compare content and content +// Hint: 2-40 consider defining the comparison with `by` or choosing a different `key` +#((1, []), (1, [])).sorted(key: a => a) + --- array-sorted-uncomparable --- // Error: 2-26 cannot compare content and content +// Hint: 2-26 consider choosing a `key` or defining the comparison with `by` #([Hi], [There]).sorted() --- array-sorted-uncomparable-lengths --- // Error: 2-26 cannot compare 3em with 2pt +// Hint: 2-26 consider choosing a `key` or defining the comparison with `by` #(1pt, 2pt, 3em).sorted() --- array-sorted-key-function-positional-2 --- @@ -555,4 +562,5 @@ --- issue-6285-crashed-with-sorting-non-total-order --- // Error: 2-66 cannot compare none and string +// Hint: 2-66 consider choosing a `key` or defining the comparison with `by` #(("a", "b", "c", "d", "e", "z") * 3 + ("c", none, "a")).sorted() diff --git a/tests/suite/pdftags/break.typ b/tests/suite/pdftags/break.typ index 57eeb063bb..fe355db278 100644 --- a/tests/suite/pdftags/break.typ +++ b/tests/suite/pdftags/break.typ @@ -30,5 +30,4 @@ Foo #quote($$ + parbreak()) #show heading: v(0pt) + [A] // Error: 3-6 internal error: tags weren't properly closed (occurred at crates/typst-pdf/src/tags/tree/build.rs:187:9) // Hint: 3-6 please report this as a bug -// Hint: 3-6 set `RUST_BACKTRACE` to `1` or `full` to capture a backtrace #[= A]B diff --git a/website/metadata.json b/website/metadata.json index f0b784e316..b5c86fee26 100644 --- a/website/metadata.json +++ b/website/metadata.json @@ -1,7 +1,7 @@ { "$schema": "./typst-docs-web/metadata.schema.json", "language": "ja-JP", - "version": "0.14.1", + "version": "0.14.2", "typstOfficialUrl": "https://typst.app", "typstOfficialDocsUrl": "https://typst.app/docs/", "githubOrganizationUrl": "https://github.com/typst-jp", diff --git a/website/translation-status.json b/website/translation-status.json index 19fd912f71..2e2b94b9e5 100644 --- a/website/translation-status.json +++ b/website/translation-status.json @@ -179,6 +179,7 @@ "/docs/guides/tables/": "untranslated", "/docs/guides/accessibility/": "translated", "/docs/changelog/": "translated", + "/docs/changelog/0.14.2/": "untranslated", "/docs/changelog/0.14.1/": "untranslated", "/docs/changelog/0.14.0/": "translated", "/docs/changelog/0.13.1/": "translated",