tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 451979278c24abac24eb482e75cfe9e41c4bbec6
parent e34c7c802d31a19ab860b94898d2d1d28b4a36aa
Author: Nicolas Silva <nical@fastmail.com>
Date:   Mon, 13 Oct 2025 09:07:54 +0000

Bug 1978773 - Fix validatation of precise gradient addresses. r=lsalzman

The existing function is overly conservative for precise gradients because the latter require less storage per gradient stop.

Differential Revision: https://phabricator.services.mozilla.com/D268169

Diffstat:
Mgfx/wr/glsl-to-cxx/src/hir.rs | 8++++++++
Mgfx/wr/swgl/src/swgl_ext.h | 14++++++++++++++
Mgfx/wr/webrender/res/ps_quad_gradient.glsl | 9++++-----
3 files changed, 26 insertions(+), 5 deletions(-)

diff --git a/gfx/wr/glsl-to-cxx/src/hir.rs b/gfx/wr/glsl-to-cxx/src/hir.rs @@ -3956,6 +3956,14 @@ pub fn ast_to_hir(state: &mut State, tu: &syntax::TranslationUnit) -> Translatio vec![Type::new(Sampler2D), Type::new(IVec2), Type::new(Int)], RunClass::Scalar, ); + declare_function_ext( + state, + "swgl_validateGradientFromStops", + None, + Type::new(Int), + vec![Type::new(Sampler2D), Type::new(IVec2), Type::new(Int)], + RunClass::Scalar, + ); declare_function( state, "swgl_commitLinearGradientRGBA8", diff --git a/gfx/wr/swgl/src/swgl_ext.h b/gfx/wr/swgl/src/swgl_ext.h @@ -1349,6 +1349,20 @@ static inline int swgl_validateGradient(sampler2D sampler, ivec2_scalar address, : -1; } +static inline int swgl_validateGradientFromStops(sampler2D sampler, ivec2_scalar address, + int entries) { + // 1px (4 floats per color stop). + int colors_size = entries; + // 4 stop offsets (4 floats) per px. + int stops_size = ((entries + 3) & ~3) / 4; + return sampler->format == TextureFormat::RGBA32F && address.y >= 0 && + address.y < int(sampler->height) && address.x >= 0 && + address.x < int(sampler->width) && entries > 0 && + address.x + colors_size + stops_size <= int(sampler->width) + ? address.y * sampler->stride + address.x * 4 + : -1; +} + static inline WideRGBA8 sampleGradient(sampler2D sampler, int address, Float entry) { assert(sampler->format == TextureFormat::RGBA32F); diff --git a/gfx/wr/webrender/res/ps_quad_gradient.glsl b/gfx/wr/webrender/res/ps_quad_gradient.glsl @@ -365,11 +365,9 @@ void swgl_drawSpanRGBA8() { int stop_count = v_gradient_header.y; int colors_address = v_gradient_header.w; - int colors_addr = swgl_validateGradient(sGpuBufferF, get_gpu_buffer_uv(colors_address), - stop_count); - int offsets_addr = swgl_validateGradient(sGpuBufferF, get_gpu_buffer_uv(colors_address + stop_count), - stop_count); - if (offsets_addr < 0 || colors_addr < 0) { + int colors_addr = swgl_validateGradientFromStops(sGpuBufferF, get_gpu_buffer_uv(colors_address), + stop_count); + if (colors_addr < 0) { // The gradient is invalid, this should not happen. We can't fall back to // the regular shader code because it expects the gradient stop offsets // to be laid out for a tree traversal but we laid them out linearly because @@ -379,6 +377,7 @@ void swgl_drawSpanRGBA8() { return; } + int offsets_addr = colors_addr + stop_count * 4; vec2 pos = v_interpolated_data.xy; float start_radius = v_flat_data.x; bool repeat = v_gradient_header.z != 0.0;