forked from pyrite-dev/milsko
added wip fuzzer, fixed alot of memory leaks with wayland
This commit is contained in:
parent
e41dbd43c1
commit
3e49278a15
5 changed files with 167 additions and 63 deletions
|
|
@ -41,6 +41,7 @@ typedef struct wayland_call_table {
|
|||
MwBool has_dbus;
|
||||
#endif
|
||||
|
||||
int (*wl_display_dispatch)(struct wl_display* display);
|
||||
int (*wl_display_dispatch_pending)(struct wl_display* display);
|
||||
void (*wl_display_disconnect)(struct wl_display* display);
|
||||
void (*wl_display_cancel_read)(struct wl_display* display);
|
||||
|
|
@ -58,6 +59,7 @@ typedef struct wayland_call_table {
|
|||
uint32_t flags, ...);
|
||||
struct wl_display* (*wl_display_connect)(const char* name);
|
||||
uint32_t (*wl_proxy_get_version)(struct wl_proxy* proxy);
|
||||
struct wl_display* (*wl_display_connect_to_fd)(int fd);
|
||||
|
||||
struct xkb_context* (*xkb_context_new)(enum xkb_context_flags flags);
|
||||
void (*xkb_context_unref)(struct xkb_context* context);
|
||||
|
|
@ -156,6 +158,7 @@ MwInline int wayland_load_funcs() {
|
|||
return 1; \
|
||||
};
|
||||
|
||||
WAYLAND_FUNC(wl_display_dispatch)
|
||||
WAYLAND_FUNC(wl_display_dispatch_pending)
|
||||
WAYLAND_FUNC(wl_display_disconnect)
|
||||
WAYLAND_FUNC(wl_display_cancel_read)
|
||||
|
|
@ -170,6 +173,7 @@ MwInline int wayland_load_funcs() {
|
|||
WAYLAND_FUNC(wl_proxy_marshal_flags)
|
||||
WAYLAND_FUNC(wl_display_connect)
|
||||
WAYLAND_FUNC(wl_proxy_get_version)
|
||||
WAYLAND_FUNC(wl_display_connect_to_fd)
|
||||
|
||||
#undef WAYLAND_FUNC
|
||||
|
||||
|
|
@ -235,6 +239,7 @@ MwInline int wayland_load_funcs() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define wl_display_dispatch wl_call_tbl.wl_display_dispatch
|
||||
#define wl_display_dispatch_pending wl_call_tbl.wl_display_dispatch_pending
|
||||
#define wl_display_disconnect wl_call_tbl.wl_display_disconnect
|
||||
#define wl_display_cancel_read wl_call_tbl.wl_display_cancel_read
|
||||
|
|
@ -249,6 +254,7 @@ MwInline int wayland_load_funcs() {
|
|||
#define wl_proxy_marshal_flags wl_call_tbl.wl_proxy_marshal_flags
|
||||
#define wl_display_connect wl_call_tbl.wl_display_connect
|
||||
#define wl_proxy_get_version wl_call_tbl.wl_proxy_get_version
|
||||
#define wl_display_connect_to_fd wl_call_tbl.wl_display_connect_to_fd
|
||||
|
||||
#define xkb_state_unref wl_call_tbl.xkb_state_unref
|
||||
#define xkb_context_new wl_call_tbl.xkb_context_new
|
||||
|
|
@ -373,11 +379,11 @@ enum _MwLLWaylandType {
|
|||
};
|
||||
|
||||
typedef struct wl_clipboard_device_context {
|
||||
union {
|
||||
struct {
|
||||
struct wl_data_device* wl;
|
||||
struct zwp_primary_selection_device_v1* zwp;
|
||||
} device;
|
||||
union {
|
||||
struct {
|
||||
struct wl_data_offer* wl;
|
||||
struct zwp_primary_selection_offer_v1* zwp;
|
||||
} offer;
|
||||
|
|
@ -409,13 +415,13 @@ struct _MwLLWayland {
|
|||
|
||||
/* Map of Wayland interfaces to their relevant setup functions. */
|
||||
struct {
|
||||
const char* key;
|
||||
char key[255];
|
||||
wayland_protocol_callback_table_t* value;
|
||||
}* wl_protocol_setup_map;
|
||||
|
||||
/* Map of Wayland interfaces to any information we keep about them once we've registered them. */
|
||||
struct {
|
||||
const char* key;
|
||||
char key[255];
|
||||
wayland_protocol_t* value;
|
||||
}* wl_protocol_map;
|
||||
|
||||
|
|
|
|||
|
|
@ -62,9 +62,7 @@ static void new_protocol(void* data, struct wl_registry* registry,
|
|||
|
||||
wayland_protocol_callback_table_t* cb = shget(self->wayland.wl_protocol_setup_map, interface);
|
||||
if(cb != NULL) {
|
||||
char* inter = malloc(strlen(interface) + 1);
|
||||
strcpy(inter, interface);
|
||||
shput(self->wayland.wl_protocol_map, inter, cb->setup(name, data));
|
||||
shput(self->wayland.wl_protocol_map, interface, cb->setup(name, data));
|
||||
/* we don't care for adding this protocol, we just use it to know if the compositor will let us have transparent surfaces */
|
||||
} else if(strcmp(interface, "wp_alpha_modifier_v1") == 0) {
|
||||
self->common.supports_transparency = MwTRUE;
|
||||
|
|
@ -651,19 +649,24 @@ static void keyboard_keymap(void* data,
|
|||
MwLL self = data;
|
||||
(void)wl_keyboard;
|
||||
|
||||
if(self->wayland.type == MWLL_WAYLAND_TOPLEVEL) {
|
||||
if(!self->wayland.parent) {
|
||||
char* map_shm;
|
||||
struct xkb_keymap* xkb_keymap;
|
||||
struct xkb_state* xkb_state;
|
||||
xkb_state = NULL;
|
||||
|
||||
assert(format == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1);
|
||||
|
||||
char* map_shm = (char*)mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
|
||||
map_shm = (char*)mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
|
||||
assert(map_shm != MAP_FAILED);
|
||||
|
||||
struct xkb_keymap* xkb_keymap = xkb_keymap_new_from_string(
|
||||
xkb_keymap = xkb_keymap_new_from_string(
|
||||
self->wayland.xkb_context, map_shm, XKB_KEYMAP_FORMAT_TEXT_V1,
|
||||
XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
munmap(map_shm, size);
|
||||
close(fd);
|
||||
|
||||
struct xkb_state* xkb_state = xkb_state_new(xkb_keymap);
|
||||
xkb_state = xkb_state_new(xkb_keymap);
|
||||
|
||||
self->wayland.xkb_keymap = xkb_keymap;
|
||||
self->wayland.xkb_state = xkb_state;
|
||||
|
|
@ -976,6 +979,7 @@ static wayland_protocol_t* wl_seat_setup(MwU32 name, MwLL ll) {
|
|||
static void wl_seat_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) {
|
||||
(void)wayland;
|
||||
free(data->listener);
|
||||
free(data);
|
||||
}
|
||||
|
||||
/* wl_output setup function */
|
||||
|
|
@ -1120,6 +1124,8 @@ static int event_loop(MwLL handle) {
|
|||
if(wl_display_dispatch_pending(wayland->display) < 0) {
|
||||
wl_display_cancel_read(wayland->display);
|
||||
}
|
||||
wl_display_flush(handle->wayland.display);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -1230,66 +1236,46 @@ static void update_buffer(MwLL self, struct _MwLLWaylandShmBuffer* buffer) {
|
|||
}
|
||||
|
||||
static void buffer_setup(struct _MwLLWaylandShmBuffer* buffer, MwU32 width, MwU32 height) {
|
||||
int stride = width * 4;
|
||||
char temp_name[] = "/tmp/milsko-wl-shm-XXXXXX";
|
||||
char temp_name_back[] = "/tmp/milsko-wl-shm-back-XXXXXX";
|
||||
int stride = width * 4;
|
||||
char temp_name[] = "/tmp/milsko-wl-shm-XXXXXX";
|
||||
|
||||
buffer->buf_size = width * height * 4;
|
||||
|
||||
buffer->fd = mkstemp(temp_name);
|
||||
buffer->fd_back = mkstemp(temp_name_back);
|
||||
|
||||
buffer->fd = mkstemp(temp_name);
|
||||
unlink(temp_name);
|
||||
unlink(temp_name_back);
|
||||
|
||||
if(posix_fallocate(buffer->fd, 0, buffer->buf_size) != 0) {
|
||||
printf("failure setting up wl_shm: could not fallocate. %s.\n", strerror(errno));
|
||||
close(buffer->fd);
|
||||
return;
|
||||
}
|
||||
if(posix_fallocate(buffer->fd_back, 0, buffer->buf_size) != 0) {
|
||||
printf("failure setting up wl_shm: could not fallocate. %s.\n", strerror(errno));
|
||||
close(buffer->fd_back);
|
||||
return;
|
||||
}
|
||||
if(ftruncate(buffer->fd, buffer->buf_size) != 0) {
|
||||
printf("failure setting up wl_shm: could not truncate. %s.\n", strerror(errno));
|
||||
close(buffer->fd);
|
||||
return;
|
||||
}
|
||||
if(ftruncate(buffer->fd_back, buffer->buf_size) != 0) {
|
||||
printf("failure setting up wl_shm: could not truncate. %s.\n", strerror(errno));
|
||||
close(buffer->fd_back);
|
||||
return;
|
||||
}
|
||||
|
||||
buffer->buf = mmap(NULL, buffer->buf_size, PROT_WRITE, MAP_SHARED, buffer->fd, 0);
|
||||
buffer->buf_back = mmap(NULL, buffer->buf_size, PROT_WRITE, MAP_SHARED, buffer->fd_back, 0);
|
||||
buffer->buf_back = malloc(buffer->buf_size);
|
||||
|
||||
fsync(buffer->fd);
|
||||
fsync(buffer->fd_back);
|
||||
|
||||
if(!(buffer->shm_pool = wl_shm_create_pool(buffer->shm, buffer->fd, buffer->buf_size))) {
|
||||
close(buffer->fd);
|
||||
printf("failure setting up wl_shm: could not create pool.\n");
|
||||
return;
|
||||
}
|
||||
if(!(buffer->shm_pool_back = wl_shm_create_pool(buffer->shm, buffer->fd_back, buffer->buf_size))) {
|
||||
printf("failure setting up wl_shm: could not create pool.\n");
|
||||
}
|
||||
buffer->shm_buffer = wl_shm_pool_create_buffer(buffer->shm_pool, 0, width, height, stride, WL_SHM_FORMAT_ARGB8888);
|
||||
buffer->shm_buffer_back = wl_shm_pool_create_buffer(buffer->shm_pool_back, 0, width, height, stride, WL_SHM_FORMAT_ARGB8888);
|
||||
buffer->setup = MwTRUE;
|
||||
buffer->shm_buffer = wl_shm_pool_create_buffer(buffer->shm_pool, 0, width, height, stride, WL_SHM_FORMAT_ARGB8888);
|
||||
buffer->setup = MwTRUE;
|
||||
}
|
||||
|
||||
static void buffer_destroy(struct _MwLLWaylandShmBuffer* buffer) {
|
||||
if(!buffer->setup) {
|
||||
return;
|
||||
}
|
||||
close(buffer->fd);
|
||||
if(buffer->buf) munmap(buffer->buf, buffer->buf_size);
|
||||
if(buffer->buf_back) free(buffer->buf_back);
|
||||
if(buffer->shm_buffer) wl_buffer_destroy(buffer->shm_buffer);
|
||||
if(buffer->shm_buffer_back) wl_buffer_destroy(buffer->shm_buffer_back);
|
||||
if(buffer->shm_pool) wl_shm_pool_destroy(buffer->shm_pool);
|
||||
if(buffer->shm_pool_back) wl_shm_pool_destroy(buffer->shm_pool_back);
|
||||
close(buffer->fd);
|
||||
close(buffer->fd_back);
|
||||
buffer->setup = MwFALSE;
|
||||
}
|
||||
|
||||
|
|
@ -1528,12 +1514,12 @@ static void destroy_toplevel(MwLL r) {
|
|||
|
||||
xdg_toplevel_destroy(r->wayland.toplevel->xdg_top_level);
|
||||
|
||||
xkb_keymap_unref(r->wayland.xkb_keymap);
|
||||
|
||||
xkb_state_unref(r->wayland.xkb_state);
|
||||
|
||||
xkb_context_unref(r->wayland.xkb_context);
|
||||
|
||||
xkb_keymap_unref(r->wayland.xkb_keymap);
|
||||
|
||||
free(r->wayland.toplevel);
|
||||
|
||||
wl_registry_destroy(r->wayland.registry);
|
||||
|
|
@ -1553,8 +1539,6 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) {
|
|||
|
||||
r->wayland.type = MWLL_WAYLAND_SUBLEVEL;
|
||||
|
||||
r->wayland.display = parent->wayland.display;
|
||||
|
||||
setup_callbacks(&r->wayland);
|
||||
|
||||
r->wayland.registry = wl_display_get_registry(parent->wayland.display);
|
||||
|
|
@ -1592,11 +1576,10 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) {
|
|||
|
||||
/* Sublevel setup function */
|
||||
static void destroy_sublevel(MwLL r) {
|
||||
backbuffer_destroy(&r->wayland);
|
||||
framebuffer_destroy(&r->wayland);
|
||||
|
||||
wl_subsurface_destroy(r->wayland.sublevel->subsurface);
|
||||
|
||||
wl_registry_destroy(r->wayland.registry);
|
||||
|
||||
free(r->wayland.sublevel);
|
||||
|
||||
r->wayland.configured = MwFALSE;
|
||||
|
|
@ -1774,6 +1757,9 @@ static void widget_setup(MwLL r, MwLL parent, int x, int y, int width, int heigh
|
|||
}
|
||||
}
|
||||
|
||||
framebuffer_destroy(&r->wayland);
|
||||
backbuffer_destroy(&r->wayland);
|
||||
|
||||
framebuffer_setup(&r->wayland);
|
||||
backbuffer_setup(&r->wayland);
|
||||
|
||||
|
|
@ -1832,8 +1818,6 @@ static void MwLLDestroyImpl(MwLL handle) {
|
|||
int select_ret;
|
||||
|
||||
event_loop(handle);
|
||||
// wl_display_cancel_read(handle->wayland.display);
|
||||
|
||||
wl_flush(handle);
|
||||
|
||||
if(pthread_mutex_timedlock(&handle->wayland.eventsMutex, &t) != 0) {
|
||||
|
|
@ -1859,7 +1843,6 @@ static void MwLLDestroyImpl(MwLL handle) {
|
|||
}
|
||||
#endif
|
||||
|
||||
buffer_destroy(&handle->wayland.cursor);
|
||||
wl_region_destroy(handle->wayland.region);
|
||||
|
||||
if(handle->wayland.supports_zwp) {
|
||||
|
|
@ -1867,10 +1850,6 @@ static void MwLLDestroyImpl(MwLL handle) {
|
|||
} else {
|
||||
wl_data_source_destroy(handle->wayland.clipboard_source.wl);
|
||||
}
|
||||
if(handle->wayland.icon != NULL) {
|
||||
buffer_destroy(handle->wayland.icon);
|
||||
wl_surface_destroy(handle->wayland.icon->surface);
|
||||
}
|
||||
|
||||
if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) {
|
||||
destroy_toplevel(handle);
|
||||
|
|
@ -1880,6 +1859,20 @@ static void MwLLDestroyImpl(MwLL handle) {
|
|||
destroy_popup(handle);
|
||||
}
|
||||
|
||||
if(handle->wayland.framebuffer.setup) {
|
||||
framebuffer_destroy(&handle->wayland);
|
||||
wl_surface_destroy(handle->wayland.framebuffer.surface);
|
||||
}
|
||||
if(handle->wayland.backbuffer.setup) {
|
||||
backbuffer_destroy(&handle->wayland);
|
||||
wl_surface_destroy(handle->wayland.backbuffer.surface);
|
||||
}
|
||||
buffer_destroy(&handle->wayland.cursor);
|
||||
if(handle->wayland.icon != NULL) {
|
||||
buffer_destroy(handle->wayland.icon);
|
||||
wl_surface_destroy(handle->wayland.icon->surface);
|
||||
}
|
||||
|
||||
for(i = 0; i < shlen(handle->wayland.wl_protocol_setup_map); i++) {
|
||||
void* ctx = shget(handle->wayland.wl_protocol_map, handle->wayland.wl_protocol_setup_map[i].key);
|
||||
|
||||
|
|
@ -1887,17 +1880,30 @@ static void MwLLDestroyImpl(MwLL handle) {
|
|||
handle->wayland.wl_protocol_setup_map[i].value->destroy(&handle->wayland, ctx);
|
||||
}
|
||||
shdel(handle->wayland.wl_protocol_map, handle->wayland.wl_protocol_setup_map[i].value);
|
||||
free(handle->wayland.wl_protocol_setup_map[i].value);
|
||||
free(ctx);
|
||||
}
|
||||
shfree(handle->wayland.wl_protocol_map);
|
||||
shfree(handle->wayland.wl_protocol_setup_map);
|
||||
|
||||
wl_keyboard_destroy(handle->wayland.keyboard);
|
||||
wl_pointer_destroy(handle->wayland.pointer);
|
||||
// wl_keyboard_destroy(handle->wayland.keyboard);
|
||||
// wl_pointer_destroy(handle->wayland.pointer);
|
||||
|
||||
if(handle->wayland.supports_zwp) {
|
||||
for(i = 0; i < arrlen(handle->wayland.clipboard_devices_zwp); i++) {
|
||||
if(handle->wayland.clipboard_devices_zwp[i]->device.zwp) zwp_primary_selection_device_v1_destroy(handle->wayland.clipboard_devices_zwp[i]->device.zwp);
|
||||
free(handle->wayland.clipboard_devices_zwp[i]);
|
||||
}
|
||||
} else {
|
||||
printf("[WARNING] Primary clipboard requested for MwLLSetClipboard, but this Wayland compositor doesn't support it.\n");
|
||||
}
|
||||
for(i = 0; i < arrlen(handle->wayland.clipboard_devices_wl); i++) {
|
||||
wl_data_device_destroy(handle->wayland.clipboard_devices_wl[i]->device.wl);
|
||||
free(handle->wayland.clipboard_devices_wl[i]);
|
||||
}
|
||||
|
||||
wl_flush(handle);
|
||||
|
||||
// free(handle);
|
||||
|
||||
if(currentlyHeldWidget == handle) {
|
||||
currentlyHeldWidget = NULL;
|
||||
}
|
||||
|
|
@ -2159,6 +2165,7 @@ static int MwLLPendingImpl(MwLL handle) {
|
|||
wl_display_cancel_read(handle->wayland.display);
|
||||
} else {
|
||||
wl_display_read_events(handle->wayland.display);
|
||||
wl_display_flush(handle->wayland.display);
|
||||
if((pending = wl_display_dispatch_pending(handle->wayland.display)) < 0) {
|
||||
wl_display_cancel_read(handle->wayland.display);
|
||||
}
|
||||
|
|
@ -2167,6 +2174,7 @@ static int MwLLPendingImpl(MwLL handle) {
|
|||
if((pending = wl_display_dispatch_pending(handle->wayland.display)) < 0) {
|
||||
wl_display_cancel_read(handle->wayland.display);
|
||||
}
|
||||
wl_display_flush(handle->wayland.display);
|
||||
}
|
||||
|
||||
if(MwWaylandAlwaysRender) {
|
||||
|
|
@ -2317,7 +2325,7 @@ static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) {
|
|||
|
||||
if(handle->wayland.configured) update_buffer(handle, handle->wayland.icon);
|
||||
|
||||
xdg_toplevel_icon_v1_add_buffer(icon, handle->wayland.icon->shm_buffer_back, 1);
|
||||
xdg_toplevel_icon_v1_add_buffer(icon, handle->wayland.icon->shm_buffer, 1);
|
||||
|
||||
xdg_toplevel_icon_manager_v1_set_icon(icon_manager, handle->wayland.toplevel->xdg_top_level, icon);
|
||||
}
|
||||
|
|
|
|||
2
tools/.gitignore
vendored
Normal file
2
tools/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
font
|
||||
fuzzer
|
||||
|
|
@ -6,7 +6,10 @@ LIBS = `freetype-config --libs`
|
|||
.PHONY: all clean
|
||||
.SUFFIXES: .c .o
|
||||
|
||||
all: font
|
||||
all: fuzzer font
|
||||
|
||||
fuzzer: fuzzer.o
|
||||
$(CC) -g -L../src/ -Wl,-R../src -lMw -o $@ fuzzer.o
|
||||
|
||||
font: font.o
|
||||
$(CC) $(LDFLAGS) -o $@ font.o $(LIBS)
|
||||
|
|
@ -15,4 +18,4 @@ font: font.o
|
|||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -f *.o font
|
||||
rm -f *.o font fuzzer
|
||||
|
|
|
|||
85
tools/fuzzer.c
Normal file
85
tools/fuzzer.c
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
#include <Mw/Milsko.h>
|
||||
|
||||
#define WIDGET_AMOUNT 1
|
||||
|
||||
int main() {
|
||||
MwWidget window, widget;
|
||||
|
||||
MwLibraryInit();
|
||||
|
||||
window = MwCreateWidget(MwWindowClass, "window", NULL, 0, 0, 400, 400);
|
||||
|
||||
while(true) {
|
||||
int r = rand() % WIDGET_AMOUNT;
|
||||
MwClass cls;
|
||||
switch(r) {
|
||||
case 0:
|
||||
cls = MwBoxClass;
|
||||
break;
|
||||
case 1:
|
||||
cls = MwButtonClass;
|
||||
break;
|
||||
case 2:
|
||||
cls = MwCheckBoxClass;
|
||||
break;
|
||||
case 3:
|
||||
cls = MwComboBoxClass;
|
||||
break;
|
||||
case 4:
|
||||
cls = MwEntryClass;
|
||||
break;
|
||||
case 5:
|
||||
cls = MwFrameClass;
|
||||
break;
|
||||
case 6:
|
||||
cls = MwImageClass;
|
||||
break;
|
||||
case 7:
|
||||
cls = MwLabelClass;
|
||||
break;
|
||||
case 8:
|
||||
cls = MwListBoxClass;
|
||||
break;
|
||||
case 9:
|
||||
cls = MwMenuClass;
|
||||
break;
|
||||
case 10:
|
||||
cls = MwNumberEntryClass;
|
||||
break;
|
||||
case 12:
|
||||
cls = MwProgressBarClass;
|
||||
break;
|
||||
case 13:
|
||||
cls = MwRadioBoxClass;
|
||||
break;
|
||||
case 14:
|
||||
cls = MwScrollBarClass;
|
||||
break;
|
||||
case 15:
|
||||
cls = MwSeparatorClass;
|
||||
break;
|
||||
// case 16:
|
||||
// cls = MwSubMenuClass;
|
||||
// break;
|
||||
case 17:
|
||||
cls = MwTreeViewClass;
|
||||
break;
|
||||
case 18:
|
||||
cls = MwViewportClass;
|
||||
break;
|
||||
default:
|
||||
cls = NULL;
|
||||
break;
|
||||
}
|
||||
if(cls) {
|
||||
widget = MwCreateWidget(cls, "Cls", window, 0, 0, 100, 100);
|
||||
}
|
||||
|
||||
if(MwPending(window)) {
|
||||
MwStep(window);
|
||||
}
|
||||
if(cls) {
|
||||
MwDestroyWidget(widget);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue