paint: Add minimum size checks for RenderingContext (#44011)

Returns an error on `RenderingContext` constructors when size is 0 in
either dimension. Also adds panics to resize functions in the same case.

Testing: Added a unit test for the new error on
`SoftwareRenderingContext::new()`.
Fixes: https://github.com/servo/servo/issues/36061

Signed-off-by: Freya Arbjerg <git@arbjerg.dev>
Co-authored-by: Martin Robinson <martin@abandonedwig.info>
This commit is contained in:
Freya Arbjerg
2026-04-08 12:18:21 +02:00
committed by GitHub
parent 280d984d3b
commit adde320fb0

View File

@@ -189,6 +189,11 @@ impl SurfmanRenderingContext {
}
fn resize_surface(&self, size: PhysicalSize<u32>) -> Result<(), Error> {
if size.width == 0 || size.height == 0 {
log::error!("Unable to resize to size under 1x1 ({size:?} provided)");
return Err(Error::Failed);
}
let size = Size2D::new(size.width as i32, size.height as i32);
let device = &mut self.device.borrow_mut();
let context = &mut self.context.borrow_mut();
@@ -309,6 +314,13 @@ pub struct SoftwareRenderingContext {
impl SoftwareRenderingContext {
pub fn new(size: PhysicalSize<u32>) -> Result<Self, Error> {
if size.width == 0 || size.height == 0 {
log::error!(
"Unable to create SoftwareRenderingContext with size under 1x1 ({size:?} provided)"
);
return Err(Error::Failed);
}
let connection = Connection::new()?;
let adapter = connection.create_software_adapter()?;
let surfman_rendering_info = SurfmanRenderingContext::new(&connection, &adapter, None)?;
@@ -350,6 +362,11 @@ impl RenderingContext for SoftwareRenderingContext {
}
fn resize(&self, size: PhysicalSize<u32>) {
assert!(
size.width > 0 && size.height > 0,
"Dimensions must be at least 1x1, got {size:?}",
);
if self.size.get() == size {
return;
}
@@ -441,6 +458,13 @@ impl WindowRenderingContext {
size: PhysicalSize<u32>,
refresh_driver: Option<Rc<dyn RefreshDriver>>,
) -> Result<Self, Error> {
if size.width == 0 || size.height == 0 {
log::error!(
"Unable to create WindowRenderingContext with size under 1x1 ({size:?} provided)"
);
return Err(Error::Failed);
}
let connection = Connection::from_display_handle(display_handle)?;
let adapter = connection.create_adapter()?;
let surfman_context = SurfmanRenderingContext::new(&connection, &adapter, refresh_driver)?;
@@ -733,6 +757,11 @@ type RenderToParentCallback = Box<dyn Fn(&glow::Context, Rect<i32>) + Send + Syn
impl OffscreenRenderingContext {
fn new(parent_context: Rc<WindowRenderingContext>, size: PhysicalSize<u32>) -> Self {
assert!(
size.width != 0 && size.height != 0,
"Dimensions must be at least 1x1, got {size:?}",
);
let framebuffer = RefCell::new(Framebuffer::new(parent_context.gleam_gl_api(), size));
Self {
parent_context,
@@ -810,6 +839,11 @@ impl RenderingContext for OffscreenRenderingContext {
}
fn resize(&self, new_size: PhysicalSize<u32>) {
assert!(
new_size.width != 0 && new_size.height != 0,
"Dimensions must be at least 1x1, got {new_size:?}",
);
let old_size = self.size.get();
if old_size == new_size {
return;
@@ -940,6 +974,7 @@ mod test {
use surfman::{Connection, ContextAttributeFlags, ContextAttributes, Error, GLApi, GLVersion};
use super::Framebuffer;
use crate::rendering_context::SoftwareRenderingContext;
#[test]
#[expect(unsafe_code)]
@@ -986,4 +1021,16 @@ mod test {
Ok(())
}
#[test]
fn test_minimum_size_error() {
let result = SoftwareRenderingContext::new(PhysicalSize {
width: 0,
height: 1,
});
match result {
Err(surfman::Error::Failed) => (),
_ => panic!("Expected {:?}", surfman::Error::Failed),
}
}
}