Hacker News

Memory-Safe WebP Decoding

30 points by computerbuster ago | 7 comments

omoikane |next [-]

I am not sure what's the current status of Wuffs-based WebP decoder, but that would be another implementation worth comparing since it shares the same goals of safety and speed.

https://github.com/google/wuffs/tree/main/std/webp

computerbuster |root |parent [-]

Thanks for the heads-up, I didn't know wuffs had a WebP decoder. Just benchmarked it (b2e6da3), and wpd is about 2-3x faster on lossy stills, 5-7x faster on lossy with alpha, and 7-8x faster on lossless on my M5 Pro (even single-threaded).

Also, wuffs is not bit-identical to libwebp, and animated WebP is completely unsupported, so I'm not sure it is a real option for WebP decoding.

nigeltao |root |parent [-]

Wuffs author here.

We got a pull request (https://github.com/google/wuffs/pull/168) in February to add lossy WebP support. Lossless WebP (which in some sense is an entirely different format, just reusing the WebP "brand") has had a Wuffs implementation for a couple of years now.

Anyway, the PR included SIMD acceleration and performance was on par with libwebp (C code).

The PR's code was, as far as I could tell, somewhat or mostly AI assisted. While that's great in terms of features, I still have more confidence in hand-crafted code.

I have since been working to manually rewrite the PR. I'd also like to add animation support, and last month I landed some Wuffs tooling changes re animated PNG, to be better able to (as a comparison baseline) decode and test animated WebP.

A lot of that manual rewrite has been committed, but the SIMD parts haven't landed yet. So yes, for what's on the main branch (not the PR), performance is not as good as libwebp yet, but landing the SIMD parts should fix that.

> wuffs is not bit-identical to libwebp

That's news to me. PR 168 says it produces pixel-identical output to libwebp. And what's in the main branch aims to be pixel-identical, e.g. for YUV to RGB conversion, it implements libwebp's formulae, not libjpeg's formule. Both use BT.601, but libwebp uses studio range and libjpeg uses full range.

Can you link to some example .webp images that are not bit-identical?

jessa0 |next |previous [-]

Related is Signal Messenger's webpsan crate, which validates webp container syntax before it is passed to libwebp. It stops just short of decoding actual pixel data, however, as the way webp works requires the entire canvas to be allocated in order to fully decode pixel data, which would have just made webpsan a full-on decoder anyway..

https://docs.rs/webpsan/latest/webpsan/

thereisno |root |parent |next [-]

Validators separate from parsers have led to many vulnerabilities in the past. There's always something the validator didn't catch that crashed the parser anyway.

computerbuster |root |parent |previous [-]

Nice, I didn't know about this!

ZeroGravitas |next |previous [-]

As part of Google's PR for their upcoming Gemini 4 Argon LLM release they said they'd rewritten a few things in rust replacing hand written simd. But I don't think webp was mentioned.

They said:

> Large Scale Codebase Migrations and Optimizations: Argon agents are working on migrating C/C++ codebases to Rust across Google — scaling from tens of thousands of lines in core libraries like re2, libgav1 up to 800K+ lines for the Fuchsia Zircon kernel. Given the criticality of many of these systems, such large-scale rewrites are undergoing rigorous automated and manual auditing, emulation testing, and review before rolling out to production.

> For libgav1, Google's open source software for decoding video, Argon agents took an existing Rust port and replaced 32K lines of SIMD code by running many rounds of profile-guided experiments, studying the compiler's output, producing safe Rust so the compiler would vectorize it automatically. The end result is a memory-safe video decoder that runs 2.7x faster than the Rust port, with identical video output, bringing it closer to the optimized C++.

|previous [-]