If init fails halfway through it will call the destroy function,
which needs some coherent stuff filled.
Allocate with calloc and fill in what cannot fail first
Found through static analysis.
The check didn't include && ws_num < 100 so l would always be 1 or 2
Instead of fixing logic it's simpler to just call snprintf twice to get
length and use that.
Also change malloc failure check to sway_assert because both callers of
this function do not do null check and would segfault...
Found through static analysis.
No logic change here, this one is mostly to please static analyzer:
- client->fd can never be -1 (and if it could, close() a few lines below
would have needed the same check)
- we never send permission denied error (dead code)
ipc_send_reply already does client disconnect on error, so we shouldn't
do it again.
We also need to process current index again as disconnect removes client
from the list we currently are processing (this is an indexed "list")
Found through static analysis.
size_t/ssize_t are 8 bytes on 64bit systems, so use the proper size to
transmit that information.
This could lead to ridiculously large alloc as len is not initialized to zero
Found through static analysis
- child would leak in the workspace_record_pid path
- removing malloc lets us get rid of That Comment nobody seems
to remember what it was about
- we would leak pipe fds on first fork failling
- we didn't return an error if second fork failed
- the final executed process still had both pipe fds
(would show up in /proc/23560/fd in launched programs)
- we would write twice to the pipe if execl failed for some reason
(e.g. if /bin/sh doesn't exist?!)
When you spawn a process with the exec command, sway now notes the
workspace you had focused and the pid of the child process, then assigns
that workspace to the child when its window appears.
Some of this is carried over from sway 0.15, but with some major
refactoring and centralization of state.
That event comes from the toplevel and not the surface, so would cause
a use-after-free on destroy if the toplevel got destroyed first:
==5454==ERROR: AddressSanitizer: heap-use-after-free on address 0x6110001ed198 at pc 0x000000472d10 bp 0x7ffc19070a80 sp 0x7ffc19070a70
WRITE of size 8 at 0x6110001ed198 thread T0
#0 0x472d0f in wl_list_remove ../common/list.c:157
#1 0x42e159 in handle_destroy ../sway/desktop/xdg_shell_v6.c:243
#2 0x7fa9e5b28ce8 in wlr_signal_emit_safe ../util/signal.c:29
#3 0x7fa9e5afd6b1 in destroy_xdg_surface_v6 ../types/xdg_shell_v6/wlr_xdg_surface_v6.c:101
#4 0x7fa9e5d98025 in destroy_resource src/wayland-server.c:688
#5 0x7fa9e5d98091 in wl_resource_destroy src/wayland-server.c:705
#6 0x7fa9e27f103d in ffi_call_unix64 (/lib64/libffi.so.6+0x603d)
#7 0x7fa9e27f09fe in ffi_call (/lib64/libffi.so.6+0x59fe)
#8 0x7fa9e5d9bf2c (/lib64/libwayland-server.so.0+0xbf2c)
#9 0x7fa9e5d983de in wl_client_connection_data src/wayland-server.c:420
#10 0x7fa9e5d99f01 in wl_event_loop_dispatch src/event-loop.c:641
#11 0x7fa9e5d98601 in wl_display_run src/wayland-server.c:1260
#12 0x40a2f4 in main ../sway/main.c:433
#13 0x7fa9e527318a in __libc_start_main ../csu/libc-start.c:308
#14 0x40b749 in _start (/opt/wayland/bin/sway+0x40b749)
0x6110001ed198 is located 152 bytes inside of 240-byte region [0x6110001ed100,0x6110001ed1f0)
freed by thread T0 here:
#0 0x7fa9e7c89880 in __interceptor_free (/lib64/libasan.so.5+0xee880)
#1 0x7fa9e5affce9 in destroy_xdg_toplevel_v6 ../types/xdg_shell_v6/wlr_xdg_toplevel_v6.c:23
#2 0x7fa9e5d98025 in destroy_resource src/wayland-server.c:688
previously allocated by thread T0 here:
#0 0x7fa9e7c89e50 in calloc (/lib64/libasan.so.5+0xeee50)
#1 0x7fa9e5b00eea in create_xdg_toplevel_v6 ../types/xdg_shell_v6/wlr_xdg_toplevel_v6.c:427
#2 0x7fa9e27f103d in ffi_call_unix64 (/lib64/libffi.so.6+0x603d)
The toplevel only notifies the compositor on destroy if it was mapped,
so only listen to events at map time.
A flash of background was happening for two reasons:
1) We were using the xsurface's dimensions to check if the surface is
ready, but these are pending dimensions.
2) In my particular setup, the default geometry of the xsurface does not
intersect any output, which prevented it from receiving a frame done
event. This made the transaction time out and the client would only
redraw once it's been rendered.