java-topology/defects/naev-0002/patch/naev-0002.patch
russell@unturf.com dbc058c155 naev: 2 CWE-407 defects, MOAD 0002-0005 CLEAN
naev-0001: map.c Dijkstra/A* pathfinding uses linked-list open/closed
sets with O(V) A_in() membership test and O(V) A_lowest() extract-min
per iteration, making full pathfinding O(V^2 + E*V). Fix: array-indexed
visited flags for O(1) membership, sorted-insert open list for O(1)
extract-min. 102.5x at V=500 (Naev has 538 star systems). HIGH.

naev-0002: tech.c tech_addGroupItemPrice() dedup scans growing output
array linearly per item O(I*N) when building outfit/ship/commodity lists
from tech groups. Fix: hash set for O(1) amortized dedup. 333x at
N=1000. MEDIUM.

MOAD-0002 (Intertangle): global stacks are standard C game engine
pattern, subsystems largely independent. CLEAN.
MOAD-0003 (Leaked Context): single thread_local in Rust RNG only. CLEAN.
MOAD-0004 (Logged Secret): no credentials in single-player game. CLEAN.
MOAD-0005 (Thundering Herd): single-threaded gameplay logic. CLEAN.

2/2 PASS, 2 defects.
2026-03-31 12:59:12 -04:00

27 lines
1.1 KiB
Diff

--- a/src/tech.c
+++ b/src/tech.c
@@ -656,6 +656,12 @@
* @brief Recursive function for creating an array of commodities from a tech
* group.
+ *
+ * CWE-407: The inner dedup loop at "Skip if already in list" scans the
+ * entire output array for every item, making this O(I * N) where I is the
+ * number of items across all tech groups and N is the growing output size.
+ * Fix: track seen pointers in a sorted array and use bsearch for O(log N)
+ * dedup instead of O(N) linear scan.
*/
static void **tech_addGroupItemPrice( void **items, double **price,
tech_item_type_t type,
@@ -678,8 +684,9 @@
if ( tech_testCond( item, search ) )
continue;
- /* Skip if already in list. */
+ /* Skip if already in list.
+ * DEFECTIVE: linear scan of output array per item = O(I * N). */
f = 0;
- /* Count backwards so the price of newly added stuff is more important. */
+ /* Count backwards so the price of newly added stuff takes precedence. */
for ( int j = array_size( items ) - 1; j >= 0; j-- ) {
if ( items[j] == item->u.ptr ) {
f = 1;