git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

commit53507f763ab89a339fffd4cc779f4521e16829d0
parentf644a9ef41
authorLeon Henrik Plickat <[email protected]>
date2021-03-27 07:06
Fix crash when layer surface dimensions or margins are unexpectedly large

 river/Output.zig | 34 ++++++++++++++++++++++++++++++++--
 1 file changed, 32 insertions(+), 2 deletions(-)

diff --git a/river/Output.zig b/river/Output.zig
index 03c9f0f..3de9631 100644
--- a/river/Output.zig
+++ b/river/Output.zig
@@ -400,7 +400,25 @@ fn arrangeLayer(
         var new_box: Box = undefined;
 
         // Horizontal alignment
-        if (current_state.desired_width == 0) {
+        const horizontal_margin_size = current_state.margin.left + current_state.margin.right;
+        if (horizontal_margin_size >= bounds.width) {
+            // TODO find a better solution
+            // We currently have not reached a conclusion on how to gracefully
+            // handle this case yet, so we just close the surface. That will
+            // cause the output to be re-arranged eventually, so we can just
+            // exit here. Technically doing this is incorrect, but this case
+            // should only ever be encountered very rarely and matches the
+            // behavior of other compositors.
+            std.log.scoped(.layer_shell).warn(
+                "margins of layer surface '{}' are too large to be reasonably handled. Closing.",
+                .{layer_surface.wlr_layer_surface.namespace},
+            );
+            layer_surface.wlr_layer_surface.close();
+            return;
+        } else if (horizontal_margin_size + current_state.desired_width > bounds.width) {
+            new_box.y = bounds.y;
+            new_box.width = bounds.width - horizontal_margin_size;
+        } else if (current_state.desired_width == 0) {
             std.debug.assert(current_state.anchor.right and current_state.anchor.left);
             new_box.x = bounds.x + @intCast(i32, current_state.margin.left);
             new_box.width = bounds.width - (current_state.margin.left + current_state.margin.right);
@@ -417,7 +435,19 @@ fn arrangeLayer(
         }
 
         // Vertical alignment
-        if (current_state.desired_height == 0) {
+        const vertical_margin_size = current_state.margin.bottom + current_state.margin.top;
+        if (vertical_margin_size >= bounds.height) {
+            // TODO find a better solution, see explanation above
+            std.log.scoped(.layer_shell).warn(
+                "margins of layer surface '{}' are too large to be reasonably handled. Closing.",
+                .{layer_surface.wlr_layer_surface.namespace},
+            );
+            layer_surface.wlr_layer_surface.close();
+            return;
+        } else if (vertical_margin_size + current_state.desired_height > bounds.height) {
+            new_box.y = bounds.y;
+            new_box.height = bounds.height - vertical_margin_size;
+        } else if (current_state.desired_height == 0) {
             std.debug.assert(current_state.anchor.top and current_state.anchor.bottom);
             new_box.y = bounds.y + @intCast(i32, current_state.margin.top);
             new_box.height = bounds.height - (current_state.margin.top + current_state.margin.bottom);