java-topology/defects/cocos2d-0003/patch/cocos2d-0003.patch
russell@unturf.com 1b98cac200 cocos2d-x: 3 CWE-407 defects, MOAD 0002-0005 CLEAN
cocos2d-0001: EventDispatcher _toRemovedListeners std::find O(L*R) MEDIUM 2.4x
cocos2d-0002: PhysicsWorld collisionBeginCallback std::find O(J_body*J_world) MEDIUM 11.6x
cocos2d-0003: BoneNode::visit _boneSkins.contains O(C*S) per frame MEDIUM 7.3x

MOAD-0002 (Intertangle): heavy singleton pattern (Director, etc.) but architectural, not patchable
MOAD-0003 (Leaked Context): no thread_local usage, CLEAN
MOAD-0004 (Logged Secret): no credential logging, CLEAN
MOAD-0005 (Thundering Herd): TextureCache uses unordered_map, CLEAN

6/6 unit tests PASS.
2026-03-31 12:10:19 -04:00

39 lines
1.8 KiB
Diff

# UNDF: UNDF-2026-000000962
--- a/cocos/editor-support/cocostudio/ActionTimeline/CCBoneNode.h
+++ b/cocos/editor-support/cocostudio/ActionTimeline/CCBoneNode.h
@@ -25,6 +25,7 @@
#pragma once
#include "base/CCProtocols.h"
+#include <unordered_set>
#include "2d/CCNode.h"
#include "renderer/CCCustomCommand.h"
#include "editor-support/cocostudio/ActionTimeline/CCTimelineMacro.h"
@@ -221,6 +222,9 @@
cocos2d::Vector<SkinNode*> _boneSkins;
+ // O(1) membership cache for _boneSkins, rebuilt when skins change.
+ // Replaces O(S) _boneSkins.contains() per child per frame in visit().
+ std::unordered_set<cocos2d::Node*> _boneSkinSet;
--- a/cocos/editor-support/cocostudio/ActionTimeline/CCBoneNode.cpp
+++ b/cocos/editor-support/cocostudio/ActionTimeline/CCBoneNode.cpp
@@ -341,7 +341,7 @@
for (; i < _children.size(); i++)
{
auto node = _children.at(i);
- if (_rootSkeleton != nullptr && _boneSkins.contains(node)) // skip skin when bone is in a skeleton
+ if (_rootSkeleton != nullptr && _boneSkinSet.count(node) > 0) // O(1) lookup
continue;
if (node && node->getLocalZOrder() < 0)
node->visit(renderer, _modelViewTransform, flags);
@@ -355,7 +355,7 @@
for (auto it = _children.cbegin() + i; it != _children.cend(); ++it)
{
auto node = (*it);
- if (_rootSkeleton != nullptr && _boneSkins.contains(node)) // skip skin when bone is in a skeleton
+ if (_rootSkeleton != nullptr && _boneSkinSet.count(node) > 0) // O(1) lookup
continue;
node->visit(renderer, _modelViewTransform, flags);
}
// In addSkin / removeSkin methods, maintain _boneSkinSet alongside _boneSkins:
// addSkin: _boneSkinSet.insert(skin);
// removeSkin: _boneSkinSet.erase(skin);