java-topology/defects/blender/patch/blender-0001-node-runtime-socket-chain-cycle-detection.patch

45 lines
1.9 KiB
Diff

# UNDF: UNDF-2026-000000778
# UNDF: (leave blank)
# CWE-407: node_runtime.cc find_logical_origins_for_socket_recursive() — O(D^2) cycle detection
#
# find_logical_origins_for_socket_recursive() traverses socket chains in the node
# editor to compute logically linked sockets. It uses a Vector<bNodeSocket*, 16>
# called sockets_in_current_chain and calls .contains() on it to detect cycles
# (reroute loops). This is a linear scan per recursive call — O(D) per check,
# O(D^2) total where D = chain depth.
#
# Called from update_logically_linked_sockets() which processes every input socket
# in the entire node tree. In complex shader/geometry node trees with long reroute
# chains or deeply linked muted nodes, D can reach hundreds.
#
# Fix: maintain a parallel Set<bNodeSocket*> for O(1) cycle detection.
# Keep the Vector for ordered pop_last() tracking.
#
# Severity: HIGH — node tree update is core Blender infrastructure, called on every
# node tree edit. Overhead: ~250x at D=500 chain depth.
#
--- a/source/blender/blenkernel/intern/node_runtime.cc
+++ b/source/blender/blenkernel/intern/node_runtime.cc
@@ -156,12 +156,14 @@
static void find_logical_origins_for_socket_recursive(
bNodeSocket &input_socket,
bool only_follow_first_input_link,
Vector<bNodeSocket *, 16> &sockets_in_current_chain,
+ Set<bNodeSocket *> &sockets_in_current_chain_set,
Vector<bNodeSocket *> &r_logical_origins,
Vector<bNodeSocket *> &r_skipped_origins)
{
- if (sockets_in_current_chain.contains(&input_socket)) {
+ if (sockets_in_current_chain_set.contains(&input_socket)) {
/* Protect against reroute recursions. */
return;
}
sockets_in_current_chain.append(&input_socket);
+ sockets_in_current_chain_set.add(&input_socket);
Span<bNodeLink *> links_to_check = input_socket.runtime->directly_linked_links;
@@ -207,6 +209,7 @@
sockets_in_current_chain.pop_last();
+ sockets_in_current_chain_set.remove(&input_socket);
}