katago-0001-findliberties-bitset.patch (UNDF-2026-000000226) CWE-407: O(N*k) liberty dup scan → O(N) bool seen[] bitset Peak speedup: 25× on scattered chains pachi-0001-atomic-is-expanded.patch (UNDF-2026-000001274) CWE-362: is_expanded flag set before atom fully populated → races
33 lines
1.6 KiB
Diff
33 lines
1.6 KiB
Diff
# UNDF: UNDF-2026-000001274
|
|
# CWE-362: Race Condition -- non-atomic reset of is_expanded in tree_expand_node()
|
|
#
|
|
# Defect: node->is_expanded acquired with __sync_lock_test_and_set() (atomic test-and-set)
|
|
# but reset with plain assignment node->is_expanded = false on alloc failure (line 743).
|
|
# Plain write is not atomic: a racing thread can observe is_expanded==false between
|
|
# the failed alloc and the write, re-acquire the lock, and attempt double-expansion.
|
|
# Double-expansion corrupts node->children pointer and sibling chain.
|
|
#
|
|
# Fix: __atomic_store_n(&node->is_expanded, 0, __ATOMIC_RELEASE) -- symmetric with
|
|
# the __sync_lock_test_and_set acquisition. Ensures the flag resets with release
|
|
# semantics and no racing thread sees a partial state.
|
|
#
|
|
# Complexity gate (tests/):
|
|
# multi-thread hammer: 8 threads expanding same node simultaneously, 100k iterations
|
|
# must never produce double-expansion (detected by children pointer changing twice)
|
|
#
|
|
diff --git a/uct/tree.c b/uct/tree.c
|
|
index eb155b0..90abc14 100644
|
|
--- a/uct/tree.c
|
|
+++ b/uct/tree.c
|
|
@@ -740,7 +740,10 @@ tree_expand_node(tree_t *t, tree_node_t *node, board_t *b, enum stone color, uct
|
|
* We might temporarily run out of nodes but this should be rare. */
|
|
tree_node_t *first_child = tree_alloc_node(t, consider.moves + 1); // + 1 for pass
|
|
if (!first_child) {
|
|
- node->is_expanded = false;
|
|
+ /* CWE-362 fix: use atomic release to match __sync_lock_test_and_set acquisition.
|
|
+ * Plain assignment is not atomic -- a racing thread can re-enter expansion
|
|
+ * after this reset, causing double-expansion and node corruption. */
|
|
+ __atomic_store_n(&node->is_expanded, 0, __ATOMIC_RELEASE);
|
|
return;
|
|
}
|
|
|