diff --git a/piet-gpu/shader/kernel4.comp b/piet-gpu/shader/kernel4.comp index 61d6cd26a..cbd1332df 100644 --- a/piet-gpu/shader/kernel4.comp +++ b/piet-gpu/shader/kernel4.comp @@ -201,7 +201,9 @@ void main() { break; case Cmd_BeginClip: for (uint k = 0; k < CHUNK; k++) { - blend_stack[blend_sp][k] = packsRGB(vec4(rgb[k], clamp(abs(area[k]), 0.0, 1.0))); + // We reject any inputs that might overflow in render_ctx.rs. + // The following is a sanity check so we don't corrupt memory should there be malformed inputs. + blend_stack[min(blend_sp, MAX_BLEND_STACK - 1)][k] = packsRGB(vec4(rgb[k], clamp(abs(area[k]), 0.0, 1.0))); } blend_sp++; cmd_ref.offset += 4; @@ -209,7 +211,7 @@ void main() { case Cmd_EndClip: blend_sp--; for (uint k = 0; k < CHUNK; k++) { - vec4 rgba = unpacksRGB(blend_stack[blend_sp][k]); + vec4 rgba = unpacksRGB(blend_stack[min(blend_sp, MAX_BLEND_STACK - 1)][k]); rgb[k] = mix(rgba.rgb, rgb[k], area[k] * rgba.a); } cmd_ref.offset += 4; diff --git a/piet-gpu/shader/kernel4.spv b/piet-gpu/shader/kernel4.spv index 28963add9..41ac3d010 100644 Binary files a/piet-gpu/shader/kernel4.spv and b/piet-gpu/shader/kernel4.spv differ diff --git a/piet-gpu/src/lib.rs b/piet-gpu/src/lib.rs index 3e46eae3f..adf20b56f 100644 --- a/piet-gpu/src/lib.rs +++ b/piet-gpu/src/lib.rs @@ -27,6 +27,8 @@ const WIDTH_IN_TILES: usize = 128; const HEIGHT_IN_TILES: usize = 96; const PTCL_INITIAL_ALLOC: usize = 1024; +const MAX_BLEND_STACK: usize = 256; + const N_CIRCLES: usize = 0; pub fn render_svg(rc: &mut impl RenderContext, filename: &str, scale: f64) { diff --git a/piet-gpu/src/render_ctx.rs b/piet-gpu/src/render_ctx.rs index e80d67d37..91ff39e24 100644 --- a/piet-gpu/src/render_ctx.rs +++ b/piet-gpu/src/render_ctx.rs @@ -15,6 +15,7 @@ use piet::{ Color, Error, FixedGradient, FontFamily, HitTestPoint, ImageFormat, InterpolationMode, IntoBrush, LineMetric, RenderContext, StrokeStyle, Text, TextLayout, TextLayoutBuilder, }; +use crate::MAX_BLEND_STACK; pub struct PietGpuImage; @@ -204,6 +205,9 @@ impl RenderContext for PietGpuRenderContext { self.elements.push(Element::BeginClip(Clip { bbox: Default::default(), })); + if self.clip_stack.len() >= MAX_BLEND_STACK { + panic!("Maximum clip/blend stack size {} exceeded", MAX_BLEND_STACK); + } self.clip_stack.push(ClipElement { bbox: None, begin_ix,