mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-09-09 06:55:37 +00:00
wayland: Avoid dereferencing a nil data offer
Pass the data device to the selection offer update functions instead of pulling it from the offer, as the offer may be nil.
This commit is contained in:
@@ -65,7 +65,7 @@ bool Wayland_SetClipboardData(SDL_VideoDevice *_this)
|
||||
SDL_WaylandDataSource *source = Wayland_DataSourceCreate(video_data);
|
||||
Wayland_DataSourceSetCallback(source, _this->clipboard_callback, _this->clipboard_userdata, _this->clipboard_sequence);
|
||||
|
||||
result = Wayland_DataDeviceSetSelection(data_device, source, (const char **)_this->clipboard_mime_types, _this->num_clipboard_mime_types);
|
||||
result = Wayland_DataDeviceSetSelectionSource(data_device, source, (const char **)_this->clipboard_mime_types, _this->num_clipboard_mime_types);
|
||||
if (!result) {
|
||||
Wayland_DataSourceDestroy(source);
|
||||
}
|
||||
|
||||
@@ -463,6 +463,8 @@ void Wayland_PrimarySelectionSourceDestroy(SDL_WaylandPrimarySelectionSource *so
|
||||
}
|
||||
}
|
||||
|
||||
static void SelectionOfferNotifyFromMIMEs(SDL_WaylandDataDevice *data_device, bool check_origin);
|
||||
|
||||
static void offer_source_done_handler(void *data, struct wl_callback *callback, uint32_t callback_data)
|
||||
{
|
||||
if (!callback) {
|
||||
@@ -485,7 +487,7 @@ static void offer_source_done_handler(void *data, struct wl_callback *callback,
|
||||
const bool source_is_external = SDL_strncmp(offer->data_device->id_str, id, length) != 0;
|
||||
SDL_free(id);
|
||||
if (source_is_external) {
|
||||
Wayland_DataOfferNotifyFromMIMEs(offer, false);
|
||||
SelectionOfferNotifyFromMIMEs(offer->data_device, false);
|
||||
} else {
|
||||
// Recursive data offer; just destroy it.
|
||||
SDL_WaylandDataDevice *data_device = offer->data_device;
|
||||
@@ -528,9 +530,9 @@ static void DataOfferCheckSource(SDL_WaylandDataOffer *offer, const char *mime_t
|
||||
}
|
||||
}
|
||||
|
||||
static void SetCurrentClipboardOffer(SDL_WaylandDataOffer *offer)
|
||||
static void UpdateSeatOffers(SDL_WaylandDataDevice *data_device)
|
||||
{
|
||||
SDL_WaylandSeat *offer_seat = offer->data_device->seat;
|
||||
SDL_WaylandSeat *offer_seat = data_device->seat;
|
||||
SDL_VideoData *video_data = offer_seat->display;
|
||||
|
||||
// Clear any existing references to the existing clipboard data before replacing the current offer.
|
||||
@@ -551,10 +553,12 @@ static void SetCurrentClipboardOffer(SDL_WaylandDataOffer *offer)
|
||||
video_data->current_data_offer_seat = offer_seat;
|
||||
}
|
||||
|
||||
void Wayland_DataOfferNotifyFromMIMEs(SDL_WaylandDataOffer *offer, bool check_origin)
|
||||
static void SelectionOfferNotifyFromMIMEs(SDL_WaylandDataDevice *data_device, bool check_origin)
|
||||
{
|
||||
int nformats = 0;
|
||||
SDL_WaylandDataOffer *offer = data_device->selection_offer;
|
||||
char **new_mime_types = NULL;
|
||||
size_t num_formats = 0;
|
||||
|
||||
if (offer) {
|
||||
size_t alloc_size = 0;
|
||||
|
||||
@@ -571,11 +575,11 @@ void Wayland_DataOfferNotifyFromMIMEs(SDL_WaylandDataOffer *offer, bool check_or
|
||||
return;
|
||||
}
|
||||
|
||||
++nformats;
|
||||
++num_formats;
|
||||
alloc_size += SDL_strlen(item->mime_type) + 1;
|
||||
}
|
||||
|
||||
alloc_size += (nformats + 1) * sizeof(char *);
|
||||
alloc_size += (num_formats + 1) * sizeof(char *);
|
||||
|
||||
new_mime_types = SDL_AllocateTemporaryMemory(alloc_size);
|
||||
if (!new_mime_types) {
|
||||
@@ -584,7 +588,7 @@ void Wayland_DataOfferNotifyFromMIMEs(SDL_WaylandDataOffer *offer, bool check_or
|
||||
}
|
||||
|
||||
// Second pass to fill.
|
||||
char *strPtr = (char *)(new_mime_types + nformats + 1);
|
||||
char *strPtr = (char *)(new_mime_types + num_formats + 1);
|
||||
item = NULL;
|
||||
int i = 0;
|
||||
wl_list_for_each(item, &offer->mimes, link) {
|
||||
@@ -596,11 +600,22 @@ void Wayland_DataOfferNotifyFromMIMEs(SDL_WaylandDataOffer *offer, bool check_or
|
||||
strPtr = stpcpy(strPtr, item->mime_type) + 1;
|
||||
i++;
|
||||
}
|
||||
new_mime_types[nformats] = NULL;
|
||||
new_mime_types[num_formats] = NULL;
|
||||
}
|
||||
|
||||
SetCurrentClipboardOffer(offer);
|
||||
SDL_SendClipboardUpdate(false, new_mime_types, nformats);
|
||||
UpdateSeatOffers(data_device);
|
||||
SDL_SendClipboardUpdate(false, new_mime_types, num_formats);
|
||||
}
|
||||
|
||||
void Wayland_DataDeviceSetSelectionOffer(SDL_WaylandDataDevice *data_device, SDL_WaylandDataOffer *offer)
|
||||
{
|
||||
// Don't notify when clearing the old selection offer if doing so will inadvertently clear the selection source.
|
||||
const bool notify = offer || (!offer && data_device->selection_offer && (!data_device->selection_offer->callback || !data_device->selection_source));
|
||||
Wayland_DataOfferDestroy(data_device->selection_offer);
|
||||
data_device->selection_offer = offer;
|
||||
if (notify) {
|
||||
SelectionOfferNotifyFromMIMEs(data_device, true);
|
||||
}
|
||||
}
|
||||
|
||||
void *Wayland_DataOfferReceive(SDL_WaylandDataOffer *offer, const char *mime_type, size_t *length, bool extended_timeout)
|
||||
@@ -726,7 +741,7 @@ void Wayland_PrimarySelectionOfferDestroy(SDL_WaylandPrimarySelectionOffer *offe
|
||||
}
|
||||
}
|
||||
|
||||
bool Wayland_DataDeviceSetSelection(SDL_WaylandDataDevice *data_device, SDL_WaylandDataSource *source, const char **mime_types, size_t mime_count)
|
||||
bool Wayland_DataDeviceSetSelectionSource(SDL_WaylandDataDevice *data_device, SDL_WaylandDataSource *source, const char **mime_types, size_t mime_count)
|
||||
{
|
||||
if (!data_device) {
|
||||
return SDL_SetError("Invalid Data Device");
|
||||
|
||||
@@ -130,7 +130,7 @@ extern void Wayland_PrimarySelectionSourceDestroy(SDL_WaylandPrimarySelectionSou
|
||||
extern void *Wayland_DataOfferReceive(SDL_WaylandDataOffer *offer, const char *mime_type, size_t *length, bool extended_timeout);
|
||||
extern void *Wayland_PrimarySelectionOfferReceive(SDL_WaylandPrimarySelectionOffer *offer, const char *mime_type, size_t *length);
|
||||
extern bool Wayland_DataOfferHasMIME(SDL_WaylandDataOffer *offer, const char *mime_type);
|
||||
extern void Wayland_DataOfferNotifyFromMIMEs(SDL_WaylandDataOffer *offer, bool check_origin);
|
||||
extern void Wayland_DataDeviceSetSelectionOffer(SDL_WaylandDataDevice *data_device, SDL_WaylandDataOffer *offer);
|
||||
extern bool Wayland_PrimarySelectionOfferHasMIME(SDL_WaylandPrimarySelectionOffer *offer, const char *mime_type);
|
||||
extern bool Wayland_DataOfferAddMIME(SDL_WaylandDataOffer *offer, const char *mime_type);
|
||||
extern bool Wayland_PrimarySelectionOfferAddMIME(SDL_WaylandPrimarySelectionOffer *offer, const char *mime_type);
|
||||
@@ -138,7 +138,7 @@ extern void Wayland_DataOfferDestroy(SDL_WaylandDataOffer *offer);
|
||||
extern void Wayland_PrimarySelectionOfferDestroy(SDL_WaylandPrimarySelectionOffer *offer);
|
||||
|
||||
// Clipboard / Primary Selection
|
||||
extern bool Wayland_DataDeviceSetSelection(SDL_WaylandDataDevice *device, SDL_WaylandDataSource *source, const char **mime_types, size_t mime_count);
|
||||
extern bool Wayland_DataDeviceSetSelectionSource(SDL_WaylandDataDevice *device, SDL_WaylandDataSource *source, const char **mime_types, size_t mime_count);
|
||||
extern bool Wayland_PrimarySelectionDeviceSetSelection(SDL_WaylandPrimarySelectionDevice *device, SDL_WaylandPrimarySelectionSource *source, const char *const *mime_types, size_t mime_count);
|
||||
extern void Wayland_DataDeviceSetSerial(SDL_WaylandDataDevice *device, uint32_t serial);
|
||||
extern void Wayland_PrimarySelectionDeviceSetSerial(SDL_WaylandPrimarySelectionDevice *device, uint32_t serial);
|
||||
|
||||
@@ -2943,13 +2943,7 @@ static void data_device_handle_selection(void *data, struct wl_data_device *wl_d
|
||||
". In data_device_listener . data_device_handle_selection on data_offer 0x%08x",
|
||||
(id ? WAYLAND_wl_proxy_get_id((struct wl_proxy *)id) : -1));
|
||||
|
||||
// Don't notify when clearing the old selection offer if doing so will inadvertently clear the selection source.
|
||||
const bool notify = offer || (!offer && data_device->selection_offer && (!data_device->selection_offer->callback || !data_device->selection_source));
|
||||
Wayland_DataOfferDestroy(data_device->selection_offer);
|
||||
data_device->selection_offer = offer;
|
||||
if (notify) {
|
||||
Wayland_DataOfferNotifyFromMIMEs(offer, true);
|
||||
}
|
||||
Wayland_DataDeviceSetSelectionOffer(data_device, offer);
|
||||
}
|
||||
|
||||
static const struct wl_data_device_listener data_device_listener = {
|
||||
|
||||
Reference in New Issue
Block a user