From a4a1e444e6c6a6a16dad18afd3c605b4a4f831f0 Mon Sep 17 00:00:00 2001 From: "russell@unturf.com" Date: Mon, 30 Mar 2026 16:52:36 -0400 Subject: [PATCH] undf: assign 741-880; stamp patches; generate_undf.py sync --- UNDF-REGISTRY.json | 4 +- .../patch/nagioscore-0001.patch | 54 +++++++++ .../NagiosCoreNotificationDedupTest.class | Bin 0 -> 4003 bytes .../test/NagiosCoreNotificationDedupTest.java | 106 ++++++++++++++++++ .../patch/nagioscore-0002.patch | 42 +++++++ .../test/NagiosCoreObjectListDedupTest.class | Bin 0 -> 3780 bytes .../test/NagiosCoreObjectListDedupTest.java | 90 +++++++++++++++ 7 files changed, 295 insertions(+), 1 deletion(-) create mode 100644 defects/nagioscore-0001/patch/nagioscore-0001.patch create mode 100644 defects/nagioscore-0001/test/NagiosCoreNotificationDedupTest.class create mode 100644 defects/nagioscore-0001/test/NagiosCoreNotificationDedupTest.java create mode 100644 defects/nagioscore-0002/patch/nagioscore-0002.patch create mode 100644 defects/nagioscore-0002/test/NagiosCoreObjectListDedupTest.class create mode 100644 defects/nagioscore-0002/test/NagiosCoreObjectListDedupTest.java diff --git a/UNDF-REGISTRY.json b/UNDF-REGISTRY.json index 5e09678be..bca458347 100644 --- a/UNDF-REGISTRY.json +++ b/UNDF-REGISTRY.json @@ -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" } diff --git a/defects/nagioscore-0001/patch/nagioscore-0001.patch b/defects/nagioscore-0001/patch/nagioscore-0001.patch new file mode 100644 index 000000000..0c988b17e --- /dev/null +++ b/defects/nagioscore-0001/patch/nagioscore-0001.patch @@ -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) { diff --git a/defects/nagioscore-0001/test/NagiosCoreNotificationDedupTest.class b/defects/nagioscore-0001/test/NagiosCoreNotificationDedupTest.class new file mode 100644 index 0000000000000000000000000000000000000000..36592bbfe3e94b76fc76e5b272780e96e720210c GIT binary patch literal 4003 zcmb7HTU1on8U8jiaAt-B1H(lK5(h;EL_w>d3>vveg#c;>HEJU{Fb6m?%)yy66w}nS zsjC;;wCN>{+B9kHg|xM{(F6%r6MIYBwX&8^T`PU)OW*p^$9844(r=$L41>^ib=G2^ zeg5wYa{o1HuCOXWx-fvpQh%u~Lh8gSBBgx4DJ;BxGu?%^yk+3@T z5yBc%xg^&;V@GB@#QHX#*@oGu}9>db(nq|g`Q&XFP)SZ%t za#4&D1*Iz1piCgJgtMq3pp0pWetnvT(z}y##Um;zuvWkwv&F@W*cqIJ6g;|&s<0I| zVxvA(BB-JY>q(k^HmOAu0wpz$X_?DwPx?q>wTg|{M21F;SY$bSX@-`qc6JHL)%mDV zQHwg#phY5GMqE<8OxcNE$cb3Jimlj2jm%&i)DmM|#K0Hm-M=F{adU!y4l(VQDeT=CnH%aGTW>FOt&^6`eL@TuR*0Tza0k|;e!7v@&xNZB$v=2H)6pX4EgRzXoPBS?aC3VV_7ES7hMkHcq zCZeOjRI0?diYUl<&WIVG(8$)F%)&_7cxshe$q=Qq0&v5WE=&q+S_LK3g4B|1<`v*? z-ydL`8w?;v4hl?}xF1(BjdLWmT1zDKxa?nvP9vewHI|03tL+mip2a8G6cWZWPOfw- zcut^fDMQ*87axen&A11j7T92?elW@+2qwnNWHb^S)28&G7L5k&(iyfAKAgvAWb>`d z*DHJTNqBIL9H-J}P_Iailhm{bim|;YnS# zutg-f!!HEZKXD*@w0A&4)Yv-(#dLkp8e_8_Gg%zFrfdBdrfmZIT>1+d>N8u3kS|k>Z_<{ zhI#RrT?x^_Di8CH5)x3mV=+B$SCF1i@Ed`RD|}kbR0Zz|Jo?{N*-;(8P{qcO#SY@; zlb16#`zw6Q!ngR&lX=-YZv*M~R|?8x1Ej7(8E=6czspmQ3ni#VDK_)6_8KKBT>pfkpm^r>n!F|663zy`fQ(*2F};^lNvM1_AHU!y z=KB&eS8vX%y2urCc>JQd$6u;kEX_;36yCs*z|mP8=d)rSPXW%nY96N-=cV3xXp1j_ zA@?0*op6=;=MV|c;mkZ@i{DC>Vw|0rM<~Uv@fz}O zgw6h^TjW$F$JBtojOuA<&f1aoL zMc#2=Ko4HT<9LbJ*z4%So9JgNJ%smg822grBX6sJ#!>tg$MARFC>L--}QgHxiK z_sacvN*uvyF@!;J9z)_1bn!Yy#666P_xZe!G4TNmJL_LT!2{$91wRlUqG*A+>XCE) zx!rQY3jLS-@2ip}yon{efIMWUHNd?qk(+*Zrx!K+1KAI7&+T%l`^5tLjGC!LF`JTt zCl^>IE5Bs%3%8V=kcpfs$J1n4{u%Px# literal 0 HcmV?d00001 diff --git a/defects/nagioscore-0001/test/NagiosCoreNotificationDedupTest.java b/defects/nagioscore-0001/test/NagiosCoreNotificationDedupTest.java new file mode 100644 index 000000000..c5c1ed09b --- /dev/null +++ b/defects/nagioscore-0001/test/NagiosCoreNotificationDedupTest.java @@ -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 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 notificationListFixed = new LinkedList<>(); + static HashSet 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); + } +} diff --git a/defects/nagioscore-0002/patch/nagioscore-0002.patch b/defects/nagioscore-0002/patch/nagioscore-0002.patch new file mode 100644 index 000000000..1ea862935 --- /dev/null +++ b/defects/nagioscore-0002/patch/nagioscore-0002.patch @@ -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; + } diff --git a/defects/nagioscore-0002/test/NagiosCoreObjectListDedupTest.class b/defects/nagioscore-0002/test/NagiosCoreObjectListDedupTest.class new file mode 100644 index 0000000000000000000000000000000000000000..0709a44b33dde098f04d1fd8ad259b75d5e70622 GIT binary patch literal 3780 zcmaJ^TW}NC8UBtXd)M;f%UY5V1|p~-HnuT1V1vxv#>I|pC^EP}l4h~ic(JT?r4=>l zCB4ua={3D1ke0M0#l57L&>6=y37yGfCl8(JW2X;&=tEvQ)0s}ElWB0jv%8jM5O_Ri z&;I-W-+%wl(Vy-u-UVVNTvF%tTZXo z?3q!_D&1L+4GK1DcnooYx)n2y8M(=%DSa8YGmc?pau2~cD={`}_=p4uP@yy+5W-eG zuAo^%3%0EaYw~i=F{g=}F*5e3HEp`?4N4SBwPU-24h=i7Q=r;4$F+Faa3;w(ZOjUk zHxCZB3|3OZ6B>45H|cg>y6Aam*&QdcR>ny>S<{&AQPC~1pMUWYdS7 zn4|;*t69akh7=g0V9t8ZE6)K17X;R>)Z^i0;iK8ComF88Z0@&a%~aeiq1>dMPp9IO z#w9auq|<(Nte1GSu1@NG6g@h3l~3ch>a2VaKcdf#~3 zKL5GRz4r1*Qh?+iOOTm3k6O!KMj`oC9?UBs4$qiGT*RlT^{4#e;doRR$Nlme zp^`JE91zP$Qp3;a;mM=PQ$wQ?qS@6H7qe|~XEJND%h}|+XIpA2Fc-ql@e2jNlpXjh zfu@xXu`-wJDYL^1r8o8ajd9)%E(^TuSA?5DpV5oaF(Z>oo4KYT+n&nL6c?1AlcLP7 z5*)oeW0qhqk?!LD_aS;Yt&+UG^ayAJnT(lr+uO`3_>I7p2Yf1Js)FAMYYxS^1vH&OYd)Mokv6P4RV&bSW&72bY89Mc?k*gDilEz zqWB7_8Up`Axq|BG2ju>$EAusK{W`AtTKo76klxVRHjl<@QpYy#+}BNGMQY@E1vEn5 zbZY2V1RGry0f>-~`~oWR4SbWn(VxIo>S>_E_v)$^_BFnPvf;pi4UIQZ-?rfn%FZwz z$twXdxAf0DQ2Ew0QrR6`z?SZcwuBl}?{-xNx}RPYW_qZMYi>MKfw?qEGNwkE17yEUn@ zx-C%~tG(M*7wFO>dZg|qI%2gEy)#iC)rhRcs$%tw&UNUqklZzRgiT{tbmIS6;#Zs9 zwb9^J@-Lw6s=Zf_s#l}6{!92aI`yu3?BTO<5eEQo9}Ok-Z_6AIGdg7i86+f&yOjfLiMzVTJ8xr2!_`s7=< z_{ZDehX@0_LQhNjT0M-+OE;hd=MW5ZMd?5!dJU>RGlz0Lt2+;vdC652iC(A70xrv% z_v&<>w_{*4%V-PhWGia%IM(qQM=P4q#KXAlh}zYI+4c{JkYoE3cYczu*x5O4{Gii}xAL|Daz4a7 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 list, HashSet 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 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 fixedList = new LinkedList<>(); + HashSet 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); + } +}