undf: assign 741-880; stamp patches; generate_undf.py sync
This commit is contained in:
parent
c9f4953656
commit
a4a1e444e6
7 changed files with 295 additions and 1 deletions
|
|
@ -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"
|
||||
}
|
||||
|
|
|
|||
54
defects/nagioscore-0001/patch/nagioscore-0001.patch
Normal file
54
defects/nagioscore-0001/patch/nagioscore-0001.patch
Normal 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) {
|
||||
Binary file not shown.
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
42
defects/nagioscore-0002/patch/nagioscore-0002.patch
Normal file
42
defects/nagioscore-0002/patch/nagioscore-0002.patch
Normal 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;
|
||||
}
|
||||
BIN
defects/nagioscore-0002/test/NagiosCoreObjectListDedupTest.class
Normal file
BIN
defects/nagioscore-0002/test/NagiosCoreObjectListDedupTest.class
Normal file
Binary file not shown.
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue