ModernUO/Projects/Server/Items
Kamron Batman 73d1ee3874
fix(network): don't leak duped-layer equipment via EquipUpdate/OPL (#2502)
## Problem

A creature equipped with two items that resolve to the **same layer** can crash the legacy EA 2D client (use-after-free). Equipment `Layer` comes from tiledata (`Layer = (Layer)ItemData.Quality`), so a **two-handed weapon and a shield both resolve to `Layer.TwoHanded`**. `Mobile.FindItemOnLayer` even documents the invariant: *"We only allow 1 item per layer. Its an implicit contract."*

## Root cause

- `SendMobileIncoming` (0x78) **dedupes by layer** (the `layers` span) and sends only the first item per slot — so a static creature is fine.
- But the per-item **`SendEquipUpdate` (0x2E)** and the item **OPL** sends do **not** dedupe. On any equip/property delta (`Item.ProcessDelta`) they fire per item and leak the second same-layer item on its own.
- The client then holds two items on one equipment slot; when that slot is torn down (e.g. a large group of such creatures and the player runs out of range → mass remove) the legacy 2D client frees one and dereferences it → UAF. ClassicUO bounds-checks and is unaffected, but the server is emitting an invalid, self-contradictory stream either way.

## Fix

Make per-item equip/OPL sends honor the same first-item-per-layer rule `SendMobileIncoming` already uses:

- `Item.IsDupedEquipLayer()` — `m_Parent is Mobile m && m.FindItemOnLayer(m_Layer) != this` (reuses the existing helper; true when an earlier item already holds this items layer).
- `Item.ProcessDelta`: early-return before the per-client loop for a duped equipped item (skips the EquipUpdate and OPL to everyone).
- `Mobile` lift-reject re-show: skip the EquipUpdate and OPL for the dupe.

No behavioral change for valid equipment (distinct layers → never duped). For the invalid duped-layer case the second item was already omitted by the 0x78 packet; this just stops it leaking back via the per-item paths.
2026-06-22 23:20:57 -07:00
..
BaseMulti.cs feat(pathfinding): multi-aware mask synthesizer + warm interior cache for house/boat cells (#2479) 2026-06-09 08:02:05 -07:00
Container.cs perf: Eliminates allocations in Container searching. (#2409) 2026-04-25 13:40:21 -07:00
Containers.cs feat: Adds Feature Flag System (#2328) 2026-02-07 12:02:57 -08:00
DecayScheduler.cs fix: Bumps deps. Updates copyrights (#2353) 2026-03-05 19:36:54 -08:00
Item.cs fix(network): don't leak duped-layer equipment via EquipUpdate/OPL (#2502) 2026-06-22 23:20:57 -07:00
Item.Enumerable.cs perf: Eliminates allocations in Container searching. (#2409) 2026-04-25 13:40:21 -07:00
Item.Messages.cs perf: Zero-alloc interpolation for SendMessage/Overhead APIs (#2434) 2026-05-03 18:04:02 -07:00
ItemBounds.cs fix: Bumps deps. Updates copyrights (#2353) 2026-03-05 19:36:54 -08:00
Layer.cs fix: Bumps deps. Updates copyrights (#2353) 2026-03-05 19:36:54 -08:00
LightType.cs fix: Bumps deps. Updates copyrights (#2353) 2026-03-05 19:36:54 -08:00
OutgoingVirtualHairPackets.cs refactor: decompose mobile/corpse hair, delete VirtualHairInfo, fix removal serial (#2462) (#2463) 2026-06-06 14:33:28 -07:00
SecureTradeContainer.cs fix: Moves containers/bods/traps/etc to serialization generator (#2310) 2026-01-07 21:55:55 -08:00
VirtualCheck.cs fix: Bumps deps. Updates copyrights (#2353) 2026-03-05 19:36:54 -08:00