Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix image delete on window.location.replace() #185

Open
wants to merge 1 commit into
base: wpebackend-fdo-1.14
Choose a base branch
from

Conversation

marex
Copy link

@marex marex commented Dec 30, 2023

When a website does JS window.location.replace(), the Webkit tears down the entire PlatformDisplayLibWPE(), which destroy surface and other resources. The destroy may happen before registered .release callbacks of e.g. wl_buffer, which may then attempt to access already free()d Image memory.

This happens with COG, where if the website does window.location.replace() then resources are destroyed and src/view-backend-exportable-fdo-egl.cpp bufferDestroyListenerCallback() is called, which frees the Image. However COG may have registered a .release callback in .export_fdo_egl_image() in exportImage, which maps to COG platform/wayland/cog-platform-wl.c on_export_wl_egl_image() -> on_dmabuf_buffer_release() and that may not have been called yet, and may even be called after bufferDestroyListenerCallback() .

The situation is worse, since during window.location.replace() the next page is being loaded, and that triggers exportBuffer() of new resources, which does findImage() and looks up Image based on assigned destroy callback bufferDestroyListenerCallback. That lookup may return Image which is just about to be destroyed, i.e. bufferDestroyListenerCallback() is already planned to be called. If that happens, COG wl_buffer .release callback would access Image which was already free()d by the bufferDestroyListenerCallback(). Worse, the image returned by findImage() have incorrect bufferResource associated with it, not the one passed to exportBuffer(), but the old one from the original image .

Fix the last part by dropping the entire findImage() mechanism, just allocate new Image for each exportBuffer() call, this happens seldom enough to not pose any significant overhead.

Fix the first part by assuring the release and destroy order is never reversed, i.e. if destroy is called first, do not free() the Image, wait for releaseImage() to be called and release the image there. If releaseImage() was called, let the bufferDestroyListenerCallback() destroy and free() the Image .

When a website does JS window.location.replace(), the Webkit tears
down the entire PlatformDisplayLibWPE(), which destroy surface and
other resources. The destroy may happen before registered .release
callbacks of e.g. wl_buffer, which may then attempt to access already
free()d Image memory.

This happens with COG, where if the website does window.location.replace()
then resources are destroyed and src/view-backend-exportable-fdo-egl.cpp
bufferDestroyListenerCallback() is called, which frees the Image. However
COG may have registered a .release callback in .export_fdo_egl_image() in
exportImage, which maps to COG platform/wayland/cog-platform-wl.c
on_export_wl_egl_image() -> on_dmabuf_buffer_release() and that may not have
been called yet, and may even be called after bufferDestroyListenerCallback() .

The situation is worse, since during window.location.replace() the next
page is being loaded, and that triggers exportBuffer() of new resources,
which does findImage() and looks up Image based on assigned destroy
callback bufferDestroyListenerCallback. That lookup may return Image
which is just about to be destroyed, i.e. bufferDestroyListenerCallback()
is already planned to be called. If that happens, COG wl_buffer .release
callback would access Image which was already free()d by the
bufferDestroyListenerCallback(). Worse, the image returned by findImage()
have incorrect bufferResource associated with it, not the one passed to
exportBuffer(), but the old one from the original image .

Fix the last part by dropping the entire findImage() mechanism, just
allocate new Image for each exportBuffer() call, this happens seldom
enough to not pose any significant overhead.

Fix the first part by assuring the release and destroy order is never
reversed, i.e. if destroy is called first, do not free() the Image,
wait for releaseImage() to be called and release the image there. If
releaseImage() was called, let the bufferDestroyListenerCallback()
destroy and free() the Image .

Signed-off-by: Marek Vasut <marex@denx.de>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant