[Proposal / discussion] Optional libvips backend for webp_transform
I maintainer di solito rispondono entro 2 giorni
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Idoneità per principianti
- 25/100
- Tipo di issue
- Funzionalità
- Chiarezza
- Da chiarire
- Stato di attività
- Attiva
- Stack tecnologico
- cmake, cpp
- Ambito
- backend, build-system
Direzione di ricerca
Start with ImageTransform.cc and the proposed CMake builds, then review the libvips and ImageMagick backend trade-offs described in the issue. Done means reaching a decision on whether to pursue libvips, which plugin form to use, and how to handle licensing, RSS behavior, and the experimental/magick relationship.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
This is a proposal for discussion, not a request to merge. It summarizes an evaluation of libvips as an alternative to ImageMagick for webp_transform, including trade-offs that argue against switching. Input from the community is wanted on whether to pursue it and in what form.
Motivation: attack surface
webp_transform decodes untrusted origin bodies on ET_NET threads. The case for libvips is security, not speed.
Advisory history, counted on the same basis for both libraries:
| source | ImageMagick | libvips |
|---|---|---|
| NVD keyword match | about 860 | about 29 (many assigned by VulDB in 2026) |
| GitHub security advisories | the 100 most recent span 2026-05-30 to 2026-09-27 | 12 in total, since 2023 |
ImageMagick:
- Several recent advisories appear, from their descriptions, to be reachable through plain JPEG/PNG/WebP reads that a security policy cannot block. This has not been verified against the plugin's code path.
- XMP profile parsing: DoS, infinite loop, use-after-free, over-read
- JPEG decoder information disclosure
- 8BIM use-after-free (identify path)
Image::read()sniffs the format itself, so a coder allowlist depends on a correctpolicy.xml.
libvips:
- In a build with only jpeg/png/webp/exif enabled, one of the 12 GitHub advisories is reachable: an EXIF NULL dereference, fixed in 8.18.2.
- The rest are in tiff, heif, svg, pdf, gif, radiance, ppm-source, the vips native format, and conversion ops the plugin doesn't call.
- The plugin already knows the format from its signature check, so it can call
vips_jpegload_buffer/vips_pngload_buffer/vips_webpload_bufferdirectly. libvips never sniffs. vips_operation_block_set()can block every other loader as defence in depth.- New third-party parsers come with it: libexif (24 NVD entries, 4 in 2026; optional, though disabling it drops EXIF passthrough), lcms2 (needed only for CMYK JPEGs) and GLib.
Not a motivation: speed or output size
- Throughput and CPU are a tie. libjpeg and libwebp do the work in both.
- At matched quality, standalone per-image latency is within about ±10% across image classes (measured against ImageMagick 7.1.0-1).
- Inside traffic_server with 16 clients, throughput is the same: 88–100 rps for ImageMagick 7.1.2-32 vs 92 rps for libvips, on 8 vCPU.
- Output size at equal quality matches within 1–4%.
Memory: better per image, worse per process (open risk)
Peak memory per transcode is 28–48% lower with libvips. ImageMagick 7 (Q16 HDRI) holds pixels as floats.
| image | ImageMagick | libvips |
|---|---|---|
| 1920x1277 JPEG -> WebP | 55 MB | 29 MB |
Inside traffic_server, process RSS is worse with libvips (jemalloc linked, default settings, 8 ET_NET threads, sustained transform load):
| setup | mean RSS |
|---|---|
| ImageMagick | 411 MB |
| libvips | 631 MB |
libvips + jemalloc narenas:8 |
344 MB |
ImageMagick + jemalloc narenas:8 |
351 MB |
- Cause: libvips does pixel work on its own worker threads. jemalloc's default of 4 arenas per CPU then keeps freed memory in many arenas. Allocator tuning closes the gap, but that is a process-wide setting.
- Unknown: behaviour on hosts with many more cores.
- Hazard: capping libvips' thread pool (
VIPS_MAX_THREADS=8) hung traffic_server under load. The cause wasn't confirmed (no thread dump was taken). The plugin wouldn't set it, but it is a sharp edge.
Licensing
- libvips and GLib are LGPL-2.1+, Category X under ASF policy.
- A libvips backend can only be an optional, separately installed dependency, never bundled: "the component is only needed for optional features" (https://www.apache.org/legal/resolved.html).
webp_transformis already built only when its image library is found.
What a prototype looks like
- Interface: a small
Transcoderinterface (init(),transcode()) with ImageMagick and libvips implementations.ImageTransform.cckeeps all HTTP logic. - Builds: CMake builds
webp_transform.so(ImageMagick) and/orwebp_transform_vips.so(libvips >= 8.13 via pkg-config). - libvips settings:
vips_concurrency_set(1)vips_cache_set_max(0)vips_block_untrusted_set(TRUE)- all loaders blocked except the three buffer loaders
- sequential access with
fail_on=error - dimensions checked from the header before any pixels are decoded
- Behaviour matches the ImageMagick backend on the edge cases tested:
- oversized, truncated and mislabeled bodies pass through
- CMYK converts with lcms2 (colours differ slightly for CMYK files without an embedded profile)
- EXIF orientation is preserved
- Differences to account for:
- Error log strings differ.
webp_transform_decode_limitmatchesImageMagick.. error. - libvips writes an EXIF block, so its JPEGs have no JFIF APP0 marker.
webp_transform_invalid_inputchecks forJFIF. - Output quality must be explicit, because libvips has no source-quality estimate. This fits the quality proposal in #13772.
- Error log strings differ.
Related: experimental/magick
plugins/experimental/magick runs ImageMagick command lines (MagickCommandGenesis), which can't be ported to libvips. A libvips webp_transform would not remove ImageMagick from builds that enable experimental plugins.
Questions for discussion
- Is reduced attack surface worth an LGPL optional dependency (libvips + GLib) and a second backend to maintain?
- If yes, should libvips be an alternative build of the same plugin, a separate plugin, or eventually the only backend?
- Can we accept the RSS behaviour under default jemalloc settings, or would we need guidance or tuning? Data from larger hosts would help.
- Should
experimental/magickstay as is, independent of this?
Method
- Host: 8 vCPU (Ice Lake), EL9, gcc 11.
- Libraries: ImageMagick 7.1.2-32 (Q16 HDRI, OpenMP, open policy; standalone latency also on 7.1.0-1); libvips 8.18.7 (meson, jpeg/png/webp/exif/lcms2 only).
- Codecs: libwebp 1.2.0, libpng 1.6.37, libjpeg-turbo 2.0.90.
- Corpus:
- 36 web JPEGs (500–1920 px)
- 24 Kodak PNGs
- 8 RGBA logos
- 28 WebP
- edge cases
- Test: traffic_server
master(RelWithDebInfo, jemalloc 5.2.1), cache off for load runs, 16 clients for 60 s, RSS sampled every second. - Harness and full data available on request.
- Lingua principale
- C++
- Stelle
- 2k
- Fork
- 878
- Merge medio
- 3g 16h
- PR unite (30g)
- 91
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Nessun modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di apache/trafficserver
-
Bug HTTP Support
Difficoltà 2/5 1-3 ore Idoneità per principianti 74/100
apache/trafficserver#13118 ·
I maintainer di solito rispondono entro 2 giorni
-
header_rewrite: rm-destination after set-destination URL crashes traffic_serverForse già presa @moonchen l’ha presa 5 giorni fa. ApertaBug Crash header_rewrite Plugins
apache/trafficserver#13800 · 1 assegnatario ·
I maintainer di solito rispondono entro 2 giorni
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 48/100
apache/trafficserver#13798 ·
I maintainer di solito rispondono entro 2 giorni
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 48/100
apache/trafficserver#13784 ·
I maintainer di solito rispondono entro 2 giorni
-
Plugins
Difficoltà 5/5 Più di una settimana Idoneità per principianti 35/100
apache/trafficserver#13774 ·
I maintainer di solito rispondono entro 2 giorni
Tutte le issue di apache/trafficserver
Issue simili
-
Incorrect Link in README.mdForse già presa Una pull request collegata a questa issue è aperta o già unita. Aperta
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 95/100
flameshot-org/flameshot#4996 ·
I maintainer di solito rispondono entro 2 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 64/100
utopia-rise/godot-jvm#1004 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
I maintainer di solito rispondono entro 3 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
I maintainer di solito rispondono entro 1 giorno
-
chore(build): TxCoordinator.cpp uses the deprecated shared_ptr atomic free functionsForse già presa @w5jwp l’ha presa oggi. Aperta
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 84/100
aethersdr/AetherSDR#6368 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno