Skip to content

use binder asset vscode.svg has mismatched mask units, causing macOS thumbnailing to allocate terabytes of RAM #14907

Open

Description

@lestephen

I have:

  • searched the issue tracker for similar issues
  • installed the latest version of Quarto CLI (reproduced on 1.10.18, and confirmed the file is unchanged on main)
  • formatted my issue following the Bug Reports guide

Bug description

src/resources/use/binder/vscode.svg contains a <mask> whose units and values disagree:

<mask id="mask-2" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox"
      x="-15" y="-15" width="1009.27778" height="1006.4">

maskUnits="objectBoundingBox" means x/y/width/height are fractions of the object bounding box, but the values are plainly user-space pixel values (they match the <rect> on the next line, which is correctly declared userSpaceOnUse). This looks like a Sketch export artifact.

Taken literally, against the ~980x980 bounding box, the mask region is:

~989,000 x ~986,000 px  =  ~9.8e11 pixels  =  ~3.5 TiB at 4 bytes/px

Browsers clamp this, so web output is unaffected and the bug is invisible in normal Quarto use. macOS ImageIO does not clamp. It allocates the region in 128 MiB tiles, so any macOS process that thumbnails or rasterizes this file (Finder, Spotlight, QuickLook, sips) balloons until the kernel kills it.

Because QuickLook treats the kill as a transient failure, it respawns and retries indefinitely. On my machine this pinned load average above 400 and drove the system into swap thrash until I tracked it down. vmmap on one extension instance:

Physical footprint: 162.1G
REGION TYPE           VIRTUAL  RESIDENT   DIRTY   SWAPPED  COUNT
CG Image               162.1G     14.6G   14.6G    147.5G   1297

1,297 regions of exactly 128 MiB, which is the tiled allocation of that mask surface.

Steps to reproduce

No Quarto invocation is needed. The shipped asset alone reproduces it on macOS:

# fetch the file exactly as shipped
curl -sO https://raw.githubusercontent.com/quarto-dev/quarto-cli/main/src/resources/use/binder/vscode.svg

# rasterize it with any macOS ImageIO consumer.
# NOTE: this is capped at 3 GB on purpose. Without the watchdog it will
# consume all available RAM and drive the machine into swap thrash.
sips -s format png --out out.png vscode.svg & P=$!
while R=$(ps -o rss= -p $P 2>/dev/null | tr -d ' '); [ -n "$R" ]; do
  echo "RSS: $((R/1024)) MB"
  [ "$R" -gt 3145728 ] && { kill -9 $P; echo "runaway, killed"; break; }
  sleep 1
done

A 2,380 byte file reaches 12.6 GB RSS within 2 seconds if left uncapped.

In normal use the trigger is simply having Quarto installed and letting Finder or Spotlight touch share/use/binder/, which is what happened here.

Actual behavior

Rasterizing the shipped vscode.svg allocates unbounded memory (observed 162 GB physical footprint) until the process is killed. Under QuickLook this becomes an infinite respawn loop that degrades the whole machine.

Expected behavior

The asset rasterizes in a few MB, like every other SVG Quarto ships.

Suggested fix

Delete the incorrect maskUnits and its associated values, and let the SVG defaults apply (objectBoundingBox with -10%/-10%/120%/120%), which comfortably covers the artwork plus its 30 unit stroke:

-        <mask id="mask-2" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="-15" y="-15" width="1009.27778" height="1006.4">
+        <mask id="mask-2" maskContentUnits="userSpaceOnUse">

Verification I ran on this change:

  • Visually lossless. Headless Chrome renders of the original and the patched file are byte-for-byte identical: 0 differing pixels out of 1,028,180.
  • Memory safe. Peak RSS drops from >12 GB to 1-2 MB, tested at 32, 128, 512 and 2048 px output.
  • I also tested explicit maskUnits="userSpaceOnUse" with a widened region; it is equally correct, but the above needs no magic numbers. Note that keeping userSpaceOnUse with the existing width/height is subtly wrong: it clips the outer white stroke by a few pixels at the edges.

The file has been unchanged since it was added in 411ebc3 ("Baseline implementation of re-entrant quarto use binder command", 2023-09-06), so this affects all releases since.

Happy to open a PR if useful.

Your environment

  • IDE: n/a (reproduced from the shell)
  • OS: macOS 27.0 (build 26A428), Apple Silicon (arm64)

Quarto check output

Quarto 1.10.18
[✓] Checking environment information...
[✓] Checking versions of quarto binary dependencies...
      Pandoc version 3.10.0: OK
      Dart Sass version 1.101.0: OK
      Deno version 2.7.14: OK
      Typst version 0.15.1: OK
[✓] Checking versions of quarto dependencies......OK
[✓] Checking Quarto installation......OK
      Version: 1.10.18
      Path: /Applications/quarto/bin
[✓] Checking tools....................OK
      TinyTeX: (not installed)
      Chrome Headless Shell: (not installed)
      VeraPDF: (not installed)
[✓] Checking LaTeX....................OK
      Using: Installation From Path
[✓] Checking Chrome Headless....................OK
[✓] Checking basic markdown render....OK
[✓] Checking R installation...........(None)
[✓] Checking Python 3 installation....OK
      Version: 3.14.7
      Jupyter: 5.9.1

Investigation was AI-assisted and the findings above (repro, render comparison, memory measurements) were reviewed and verified by me before filing.

Activity

  1. cscheid commented on Sep 18, 2026

    @cscheid
    Member

    Thanks for the report. I'm genuinely surprised by this, since it feels like the kind of loud failure that would have surfaced before. That file has lived in the repo since 2023-09-06 - over three years!

  2. added this to the v1.11 milestone on Sep 18, 2026
  3. cscheid commented on Sep 18, 2026

    @cscheid
    Member

    We definitely want to fix it, but it seems that web browsers know to use a better rasterizer, since this is what Firefox (in macOS!) shows me live.

    Image

    In other words, I think this is not entirely on us.

    I'm inclined to fix this bug, but I'm curious: how did you run into this bug?

  4. lestephen commented on Sep 19, 2026

    @lestephen
    Author

    I found it by chance while investigating a system-wide slowdown. My Mac became nearly unusable, with load average above 400 and ImageThumbnailExtension at 37G. vmmap showed a 162.1 GiB footprint for one instance, mostly swapped out.

    Repeated lsof checks showed the QuickLook thumbnails agent holding Quarto's vscode.svg open while extension processes changed. Running sips on that file reproduced the excessive allocation independently of Quarto, and changing the mask configuration made it complete normally. I still do not know what originally requested the thumbnail.

    I rechecked the measurements and need to correct two details in my report: the fixed renders peak at about 20-41 MiB, not 1-2 MB; the original polling interval missed their peaks. The watchdog is also a sampled stop threshold, not a hard memory cap. The multi-TiB figure was theoretical, not measured resident RAM. The final fix still produces identical pixels in the Chrome and librsvg comparisons.

    I agree the renderer has a problem too. My explanation of its allocation and retry behavior was more specific than the evidence supports.

    One possible clue to why this surfaced now: receipts show Quarto installed July 26, then macOS 27.0 on September 14. The failure occurred three days after the OS upgrade. I do not know whether this file was ever thumbnailed under macOS 26, and I do not have another Mac available to compare.

  5. modified the milestones: v1.11, v1.12 on Oct 29, 2026
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

    binderbugSomething isn't working

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions