diff --git a/render/allocator/udmabuf.c b/render/allocator/udmabuf.c index 8a7109a..93cde90 100644 --- a/render/allocator/udmabuf.c +++ b/render/allocator/udmabuf.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +48,10 @@ static struct wlr_buffer *allocator_create_buffer( struct wlr_allocator *wlr_allocator, int width, int height, const struct wlr_drm_format *format) { struct wlr_udmabuf_allocator *allocator = wl_container_of(wlr_allocator, allocator, base); + if (width <= 0 || height <= 0) { + wlr_log(WLR_ERROR, "Invalid buffer dimensions"); + return NULL; + } const struct wlr_pixel_format_info *info = drm_get_pixel_format_info(format->format); @@ -67,9 +72,26 @@ static struct wlr_buffer *allocator_create_buffer( } wlr_buffer_init(&buffer->base, &buffer_impl, width, height); + // llvmpipe accesses render targets in 4x4 pixel blocks, using aligned + // vector loads even for partially covered blocks. Pad rows to preserve + // alignment and leave room for a complete block at the bottom edge. + // Include bytes_per_block so packed formats keep a valid pixel stride. + int32_t min_stride = pixel_format_info_min_stride(info, width); + int32_t stride_alignment = 16 * info->bytes_per_block; + if (min_stride <= 0 || min_stride > INT32_MAX - (stride_alignment - 1)) { + wlr_log(WLR_ERROR, "Invalid buffer stride"); + goto err_buffer; + } + int32_t stride = (min_stride + stride_alignment - 1) / + stride_alignment * stride_alignment; + size_t padded_height = ((size_t)height + 3) & ~(size_t)3; + if (padded_height > (SIZE_MAX - (size_t)page_size + 1) / (size_t)stride) { + wlr_log(WLR_ERROR, "Buffer size overflow"); + goto err_buffer; + } + // TODO: consider using a single file for multiple buffers - int stride = pixel_format_info_min_stride(info, width); // TODO: align? - size_t size = stride * height; + size_t size = (size_t)stride * padded_height; if (size % page_size != 0) { size += page_size - (size % page_size); }