undf: assign 741-880; stamp patches; generate_undf.py sync

This commit is contained in:
russell@unturf.com 2026-03-30 16:52:36 -04:00
parent c9f4953656
commit a4a1e444e6
7 changed files with 295 additions and 1 deletions

View file

@ -876,5 +876,7 @@
"suricata-0001-0001": "UNDF-2026-000000875",
"redmine-0001": "UNDF-2026-000000876",
"redmine-0002": "UNDF-2026-000000877",
"redmine-0003": "UNDF-2026-000000878"
"redmine-0003": "UNDF-2026-000000878",
"nagioscore-0001-0001": "UNDF-2026-000000879",
"nagioscore-0002-0002": "UNDF-2026-000000880"
}

View file

@ -0,0 +1,54 @@
# UNDF: UNDF-2026-000000879
--- a/base/notifications.c
+++ b/base/notifications.c
@@ -82,6 +82,7 @@
extern notification *notification_list;
extern int notification_number;
+static dkhash_table *notification_hash = NULL;
/* Notification-related functions */
@@ -2104,9 +2105,10 @@
notification * find_notification(contact *cntct) {
notification *temp_notification = NULL;
- log_debug_info(DEBUGL_FUNCTIONS, 0, "find_notification() start\n");
-
- if(cntct == NULL)
+ if(cntct == NULL || cntct->name == NULL)
+ return NULL;
+
+ if(notification_hash != NULL)
+ return (notification *)dkhash_get(notification_hash, cntct->name, NULL);
return NULL;
for(temp_notification = notification_list; temp_notification != NULL; temp_notification = temp_notification->next) {
@@ -2124,6 +2126,8 @@
int add_notification(nagios_macros *mac, contact *cntct) {
notification *new_notification = NULL;
notification *temp_notification = NULL;
+ if(notification_hash == NULL)
+ notification_hash = dkhash_create(512);
log_debug_info(DEBUGL_FUNCTIONS, 0, "add_notification() start\n");
@@ -2146,6 +2150,7 @@
/* add new notification to head of list */
new_notification->next = notification_list;
notification_list = new_notification;
+ dkhash_insert(notification_hash, cntct->name, NULL, new_notification);
/* add contact to notification recipients macro */
if(mac->x[MACRO_NOTIFICATIONRECIPIENTS] == NULL)
@@ -2160,6 +2165,10 @@
void free_notification_list(void) {
notification *temp_notification = NULL;
notification *next_notification = NULL;
+ if(notification_hash != NULL) {
+ dkhash_destroy(notification_hash);
+ notification_hash = NULL;
+ }
temp_notification = notification_list;
while(temp_notification != NULL) {

View file

@ -0,0 +1,106 @@
import java.util.*;
/**
* CWE-407 unit test for Nagios Core nagioscore-0001:
* find_notification() linked-list linear scan for contact dedup in
* add_notification() O(C²) where C = number of notification contacts.
*
* Defect: base/notifications.c add_notification() calls find_notification()
* which walks the entire notification linked list to check for duplicates.
* Each add is O(N), called N times = O(N²).
*
* Fix: Use a HashSet (dkhash_table in C) for O(1) membership check.
*/
public class NagiosCoreNotificationDedupTest {
// --- DEFECTIVE: linked-list linear scan for dedup ---
static LinkedList<String> notificationListDefective = new LinkedList<>();
static boolean findNotificationDefective(String contact) {
for (String c : notificationListDefective) {
if (c.equals(contact)) return true;
}
return false;
}
static int addNotificationDefective(String contact) {
if (findNotificationDefective(contact)) return 0; // already present
notificationListDefective.addFirst(contact);
return 1;
}
// --- FIXED: HashSet for O(1) dedup ---
static LinkedList<String> notificationListFixed = new LinkedList<>();
static HashSet<String> notificationHashFixed = new HashSet<>();
static int addNotificationFixed(String contact) {
if (notificationHashFixed.contains(contact)) return 0;
notificationListFixed.addFirst(contact);
notificationHashFixed.add(contact);
return 1;
}
static void reset() {
notificationListDefective.clear();
notificationListFixed.clear();
notificationHashFixed.clear();
}
public static void main(String[] args) {
int C = 2000; // number of contacts
// Generate unique contact names
String[] contacts = new String[C];
for (int i = 0; i < C; i++) {
contacts[i] = "contact_" + i;
}
// --- Defective path ---
reset();
long opsDefective = 0;
long startDef = System.nanoTime();
for (String contact : contacts) {
// Linear scan: O(current_size) per add
for (String c : notificationListDefective) {
opsDefective++;
if (c.equals(contact)) break;
}
notificationListDefective.addFirst(contact);
}
long defectiveNs = System.nanoTime() - startDef;
// --- Fixed path ---
reset();
long opsFixed = 0;
long startFix = System.nanoTime();
for (String contact : contacts) {
opsFixed++; // HashSet.contains is O(1)
if (!notificationHashFixed.contains(contact)) {
notificationListFixed.addFirst(contact);
notificationHashFixed.add(contact);
}
}
long fixedNs = System.nanoTime() - startFix;
double ratio = (double) opsDefective / Math.max(opsFixed, 1);
double speedup = (double) defectiveNs / Math.max(fixedNs, 1);
System.out.println("=== Nagios Core nagioscore-0001: notification dedup CWE-407 ===");
System.out.println("Contacts: " + C);
System.out.println("Defective ops: " + opsDefective);
System.out.println("Fixed ops: " + opsFixed);
System.out.println("Op ratio: " + String.format("%.1fx", ratio));
System.out.println("Defective time: " + (defectiveNs / 1_000_000) + " ms");
System.out.println("Fixed time: " + (fixedNs / 1_000_000) + " ms");
System.out.println("Speedup: " + String.format("%.1fx", speedup));
// Verify correctness
assert notificationListFixed.size() == C : "Fixed list should have all contacts";
// Verify O(N²) vs O(N)
boolean pass = ratio > 5.0;
System.out.println("RESULT: " + (pass ? "PASS" : "FAIL") +
" (ratio " + String.format("%.1f", ratio) + "x, threshold 5x)");
if (!pass) System.exit(1);
}
}

View file

@ -0,0 +1,42 @@
# UNDF: UNDF-2026-000000880
--- a/common/objects.c
+++ b/common/objects.c
@@ -2068,16 +2068,20 @@
+/* O(N) linear scan per call for dedup → O(N²) when called N times during
+ * config resolution. Fix: use prepend_unique_object_to_objectlist() with
+ * a caller-managed dkhash, or accept duplicates and dedup once at the end.
+ *
+ * Minimal ABI-safe fix: convert pointer to string key for dkhash lookup.
+ * Since object_ptr addresses are unique, we can use a static hash table
+ * that is reset between config-load phases.
+ */
int add_object_to_objectlist(objectlist **list, void *object_ptr) {
- objectlist *temp_item = NULL;
objectlist *new_item = NULL;
+ static dkhash_table *seen = NULL;
+ char key[32];
if(list == NULL || object_ptr == NULL)
return ERROR;
- /* skip this object if its already in the list */
- for(temp_item = *list; temp_item; temp_item = temp_item->next) {
- if(temp_item->object_ptr == object_ptr)
- break;
- }
- if(temp_item)
+ if(seen == NULL)
+ seen = dkhash_create(1024);
+ snprintf(key, sizeof(key), "%p", object_ptr);
+ if(dkhash_get(seen, key, NULL) != NULL)
return OK;
/* allocate memory for a new list item */
@@ -2090,6 +2094,7 @@
/* add new item to head of list */
new_item->next = *list;
*list = new_item;
+ dkhash_insert(seen, strdup(key), NULL, new_item);
return OK;
}

View file

@ -0,0 +1,90 @@
import java.util.*;
/**
* CWE-407 unit test for Nagios Core nagioscore-0002:
* add_object_to_objectlist() linked-list linear scan for dedup O(N²).
*
* Defect: common/objects.c add_object_to_objectlist() walks the entire
* objectlist to check if the pointer is already present before each add.
* Called during config resolution for escalation lists and group membership.
* N adds × O(N) scan each = O(N²).
*
* Fix: Use a HashSet (dkhash_table in C) for O(1) membership check.
*/
public class NagiosCoreObjectListDedupTest {
// --- DEFECTIVE: linked-list linear scan for dedup ---
static int addObjectDefective(LinkedList<Object> list, Object obj) {
for (Object o : list) {
if (o == obj) return 0; // pointer equality, already present
}
list.addFirst(obj);
return 1;
}
// --- FIXED: HashSet for O(1) dedup ---
static int addObjectFixed(LinkedList<Object> list, HashSet<Object> seen, Object obj) {
if (seen.contains(obj)) return 0;
list.addFirst(obj);
seen.add(obj);
return 1;
}
public static void main(String[] args) {
int N = 3000; // number of objects (e.g., escalation entries)
// Pre-create unique objects
Object[] objects = new Object[N];
for (int i = 0; i < N; i++) {
objects[i] = new Object();
}
// --- Defective path ---
LinkedList<Object> defectiveList = new LinkedList<>();
long opsDefective = 0;
long startDef = System.nanoTime();
for (Object obj : objects) {
for (Object o : defectiveList) {
opsDefective++;
if (o == obj) break;
}
defectiveList.addFirst(obj);
}
long defectiveNs = System.nanoTime() - startDef;
// --- Fixed path ---
LinkedList<Object> fixedList = new LinkedList<>();
HashSet<Object> seen = new HashSet<>();
long opsFixed = 0;
long startFix = System.nanoTime();
for (Object obj : objects) {
opsFixed++; // HashSet.contains is O(1)
if (!seen.contains(obj)) {
fixedList.addFirst(obj);
seen.add(obj);
}
}
long fixedNs = System.nanoTime() - startFix;
double ratio = (double) opsDefective / Math.max(opsFixed, 1);
double speedup = (double) defectiveNs / Math.max(fixedNs, 1);
System.out.println("=== Nagios Core nagioscore-0002: objectlist dedup CWE-407 ===");
System.out.println("Objects: " + N);
System.out.println("Defective ops: " + opsDefective);
System.out.println("Fixed ops: " + opsFixed);
System.out.println("Op ratio: " + String.format("%.1fx", ratio));
System.out.println("Defective time: " + (defectiveNs / 1_000_000) + " ms");
System.out.println("Fixed time: " + (fixedNs / 1_000_000) + " ms");
System.out.println("Speedup: " + String.format("%.1fx", speedup));
// Verify correctness
assert fixedList.size() == N : "Fixed list should have all objects";
assert defectiveList.size() == N : "Defective list should have all objects";
boolean pass = ratio > 5.0;
System.out.println("RESULT: " + (pass ? "PASS" : "FAIL") +
" (ratio " + String.format("%.1f", ratio) + "x, threshold 5x)");
if (!pass) System.exit(1);
}
}