java-topology/whitepaper/outreach/cemu-0001.md
russell@unturf.com aeb084c9ae feat: add 30 outreach docs (batches 9-10)
Batch 9 (15): bun, bzflag (3), cake_wallet (4), calligra, caprice32 (2),
  cataclysm (3), cemu
Batch 10 (15): cemu-0002, citra, clickhouse-java, cmake (3), cocos2d (3),
  conduit, cura (2), curaengine, clamav, contiki
2026-04-14 19:51:36 -04:00

3 KiB
Raw Blame History

Cemu — CWE-407 Disclosure Brief (cemu-0001)

2026-04-14 · Patch available — awaiting upstream merge

Finding

One O(n²) defect in Cemu's Vulkan texture view system. The LatteTextureViewVk::AddDescriptorSetReference() method uses std::find on a std::vector for dedup before inserting descriptor set references. Fires during Vulkan rendering when texture views get bound to descriptor sets.

The Defect

cemu-0001 (PATCHED — HIGH): src/Cafe/HW/Latte/Renderer/Vulkan/LatteTextureViewVk.h:22

// In LatteTextureViewVk — fires per descriptor set binding:
void AddDescriptorSetReference(struct VkDescriptorSetInfo* dsInfo) {
    if (std::find(list_descriptorSets.begin(), list_descriptorSets.end(), dsInfo)
        == list_descriptorSets.end())
        list_descriptorSets.emplace_back(dsInfo);
};

list_descriptorSets is a std::vector<VkDescriptorSetInfo*>. Every time a texture view gets bound to a descriptor set, the code scans the growing vector to check for duplicates. Games with many active textures and frequent descriptor set rebinding accumulate large reference lists, making the linear scan costly.

Complexity Proof

At D=200 descriptor set references per texture view:

  • Defective: 200 insertions × average 100 comparisons = ~20,000 pointer comparisons
  • Fixed: 200 insertions × O(1) = 200 hash lookups
  • ~100× op reduction. Fires during rendering for every texture bind.

Impact

Cemu emulates the Wii U. Wii U games with complex rendering pipelines (Breath of the Wild, Mario Kart 8, Xenoblade Chronicles X) use many textures with frequent descriptor set rebinding. The quadratic cost adds per-frame overhead that scales with scene complexity.

The Fix

Replace std::vector with std::unordered_set:

// Before
std::vector<struct VkDescriptorSetInfo*> list_descriptorSets;
void AddDescriptorSetReference(struct VkDescriptorSetInfo* dsInfo) {
    if (std::find(list_descriptorSets.begin(), list_descriptorSets.end(), dsInfo)
        == list_descriptorSets.end())
        list_descriptorSets.emplace_back(dsInfo);
};

// After
// CWE-407 fix: unordered_set for O(1) dedup instead of O(D) vector scan.
std::unordered_set<struct VkDescriptorSetInfo*> list_descriptorSets;
void AddDescriptorSetReference(struct VkDescriptorSetInfo* dsInfo) {
    list_descriptorSets.insert(dsInfo);
};

Patch

Fix available: defects/cemu-0001/patch/cemu-0001.patch

Two-file patch across LatteTextureViewVk.h and LatteTextureViewVk.cpp. Replaces std::vector with std::unordered_set for descriptor set references. Updates destructor to iterate the set.

What We Ask

A patch is ready for review.

  1. Confirm receipt and assign a GitHub issue reference (cemu-project/Cemu).
  2. Assess severity — fires per texture bind during Vulkan rendering.
  3. Coordinate a disclosure date — we target 90 days from first contact.
  4. We will credit the Cemu team in the public disclosure. Preferred acknowledgment format welcome.

Contact: see cover email. This brief is confidential until coordinated disclosure.