LibWeb: Avoid stale DataTransferItem access after clearing data

Previously, clearing a DataTransfer's data removed entries from the
drag data store without updating the associated `DataTransferItem`
objects. An item obtained beforehand kept an index that no longer
referenced a valid entry, so reading its kind or type accessed an
out of bounds element of the now-empty list and crashed. We now keep
the item objects in sync when clearing data, placing any stale ones
into the disabled mode.
This commit is contained in:
Tim Ledbetter 2026-06-08 06:01:21 +01:00 committed by Andreas Kling
parent 3c4076597e
commit 525ce459fc
3 changed files with 25 additions and 7 deletions

View file

@ -319,16 +319,11 @@ void DataTransfer::clear_data(Optional<String> maybe_format)
return;
auto remove_items_from_drag_data_store = [&](Optional<String> const& format = {}) {
auto did_remove_item = false;
for (size_t i = m_associated_drag_data_store->item_list().size(); i > 0; --i) {
auto const& item = m_associated_drag_data_store->item_list().at(i - 1);
if (item.kind == DragDataStoreItem::Kind::Text && (!format.has_value() || item.type_string == *format)) {
m_associated_drag_data_store->remove_item_at(i - 1);
did_remove_item = true;
}
if (item.kind == DragDataStoreItem::Kind::Text && (!format.has_value() || item.type_string == *format))
remove_item(i - 1);
}
if (did_remove_item)
update_data_transfer_types_list();
};
// 3. If the method was called with no arguments, remove each item in the drag data store item list whose kind is

View file

@ -0,0 +1,4 @@
items.length after clearData = 0
stale item kind = ""
stale item type = ""
stale item getAsFile() = null

View file

@ -0,0 +1,19 @@
<!DOCTYPE html>
<script src="../include.js"></script>
<script>
test(() => {
const dataTransfer = new DataTransfer();
const item = dataTransfer.items.add("payload", "text/plain");
dataTransfer.clearData();
println(`items.length after clearData = ${dataTransfer.items.length}`);
// The item is now in the disabled mode, because it is not associated with a drag data store.
// DataTransferItem's kind and type should be empty string because we are in disabled mode, but other engines
// don't seem to follow the spec here.
println(`stale item kind = "${item.kind}"`);
println(`stale item type = "${item.type}"`);
println(`stale item getAsFile() = ${item.getAsFile()}`);
});
</script>