diff --git a/UNDF-REGISTRY.json b/UNDF-REGISTRY.json index 9727edc5c..c62a69596 100644 --- a/UNDF-REGISTRY.json +++ b/UNDF-REGISTRY.json @@ -892,5 +892,8 @@ "thunderbird-0005-0005": "UNDF-2026-000000891", "thunderbird-0006-0006": "UNDF-2026-000000892", "proton-0001": "UNDF-2026-000000893", - "proton-0002": "UNDF-2026-000000894" + "proton-0002": "UNDF-2026-000000894", + "forgejo-0001-0001": "UNDF-2026-000000895", + "snort3-0001-0001": "UNDF-2026-000000896", + "tryton-0001-0001": "UNDF-2026-000000897" } diff --git a/defects/forgejo-0001/patch/forgejo-0001.patch b/defects/forgejo-0001/patch/forgejo-0001.patch index ff41c3ac5..305a06f8d 100644 --- a/defects/forgejo-0001/patch/forgejo-0001.patch +++ b/defects/forgejo-0001/patch/forgejo-0001.patch @@ -1,3 +1,4 @@ +# UNDF: UNDF-2026-000000895 --- a/modules/indexer/code/search.go +++ b/modules/indexer/code/search.go @@ -50,12 +50,13 @@ type Results []*Result diff --git a/defects/pcsx2-0001/test/PatchReloadEnabledListsTest.class b/defects/pcsx2-0001/test/PatchReloadEnabledListsTest.class deleted file mode 100644 index 587f7eb03..000000000 Binary files a/defects/pcsx2-0001/test/PatchReloadEnabledListsTest.class and /dev/null differ diff --git a/defects/pcsx2-0002/test/GSCaptureCodecDedupTest.class b/defects/pcsx2-0002/test/GSCaptureCodecDedupTest.class deleted file mode 100644 index dca8215e4..000000000 Binary files a/defects/pcsx2-0002/test/GSCaptureCodecDedupTest.class and /dev/null differ diff --git a/defects/snort3-0001/patch/snort3-0001.patch b/defects/snort3-0001/patch/snort3-0001.patch index 084210ca2..bac789414 100644 --- a/defects/snort3-0001/patch/snort3-0001.patch +++ b/defects/snort3-0001/patch/snort3-0001.patch @@ -1,3 +1,4 @@ +# UNDF: UNDF-2026-000000896 --- a/src/network_inspectors/appid/service_plugins/service_discovery.cc +++ b/src/network_inspectors/appid/service_plugins/service_discovery.cc @@ -1,5 +1,6 @@ diff --git a/defects/thunderbird-0001/test/ThunderbirdAccountManagerTest.class b/defects/thunderbird-0001/test/ThunderbirdAccountManagerTest.class new file mode 100644 index 000000000..fbd85b5fd Binary files /dev/null and b/defects/thunderbird-0001/test/ThunderbirdAccountManagerTest.class differ diff --git a/defects/thunderbird-0002/test/ThunderbirdCopyServiceTest$CopyRequest.class b/defects/thunderbird-0002/test/ThunderbirdCopyServiceTest$CopyRequest.class new file mode 100644 index 000000000..7a3692854 Binary files /dev/null and b/defects/thunderbird-0002/test/ThunderbirdCopyServiceTest$CopyRequest.class differ diff --git a/defects/thunderbird-0002/test/ThunderbirdCopyServiceTest.class b/defects/thunderbird-0002/test/ThunderbirdCopyServiceTest.class new file mode 100644 index 000000000..5f5022cf8 Binary files /dev/null and b/defects/thunderbird-0002/test/ThunderbirdCopyServiceTest.class differ diff --git a/defects/thunderbird-0003/test/ThunderbirdAutoSyncManagerTest.class b/defects/thunderbird-0003/test/ThunderbirdAutoSyncManagerTest.class new file mode 100644 index 000000000..ef32b4ae5 Binary files /dev/null and b/defects/thunderbird-0003/test/ThunderbirdAutoSyncManagerTest.class differ diff --git a/defects/thunderbird-0004/test/ThunderbirdImapFlagUidStateTest.class b/defects/thunderbird-0004/test/ThunderbirdImapFlagUidStateTest.class new file mode 100644 index 000000000..7c7c8e554 Binary files /dev/null and b/defects/thunderbird-0004/test/ThunderbirdImapFlagUidStateTest.class differ diff --git a/defects/thunderbird-0005/test/ThunderbirdFilterListTest.class b/defects/thunderbird-0005/test/ThunderbirdFilterListTest.class new file mode 100644 index 000000000..f268ecc73 Binary files /dev/null and b/defects/thunderbird-0005/test/ThunderbirdFilterListTest.class differ diff --git a/defects/thunderbird-0006/test/ThunderbirdSpamWhitelistTest.class b/defects/thunderbird-0006/test/ThunderbirdSpamWhitelistTest.class new file mode 100644 index 000000000..19778ef9b Binary files /dev/null and b/defects/thunderbird-0006/test/ThunderbirdSpamWhitelistTest.class differ diff --git a/defects/tryton-0001/patch/tryton-0001-modelstorage-save-values.patch b/defects/tryton-0001/patch/tryton-0001-modelstorage-save-values.patch new file mode 100644 index 000000000..3fb9027c2 --- /dev/null +++ b/defects/tryton-0001/patch/tryton-0001-modelstorage-save-values.patch @@ -0,0 +1,25 @@ +# UNDF: UNDF-2026-000000897 +--- a/trytond/trytond/model/modelstorage.py ++++ b/trytond/trytond/model/modelstorage.py +@@ -2115,7 +2115,7 @@ + if self.id is not None and self.id >= 0: + _values, self._values = self._values, None + try: +- previous = [t.id for t in getattr(self, fname)] ++ previous = set(t.id for t in getattr(self, fname)) + finally: + self._values = _values + else: +- previous = [] ++ previous = set() + to_add = [] + to_create = [] + to_write = [] +@@ -2139,7 +2139,7 @@ + else: + if target.id in previous: +- previous.remove(target.id) ++ previous.discard(target.id) + else: + to_add.append(target.id) + target_values = target._save_values() diff --git a/defects/tryton-0001/patch/tryton-0001-modelview-changed-values.patch b/defects/tryton-0001/patch/tryton-0001-modelview-changed-values.patch new file mode 100644 index 000000000..308941f0f --- /dev/null +++ b/defects/tryton-0001/patch/tryton-0001-modelview-changed-values.patch @@ -0,0 +1,19 @@ +# UNDF: UNDF-2026-000000897 +--- a/trytond/trytond/model/modelview.py ++++ b/trytond/trytond/model/modelview.py +@@ -922,7 +922,7 @@ + init_targets = getattr(init_record, fname, []) + value = collections.defaultdict(list) +- previous = [t.id for t in init_targets if t.id] ++ previous = set(t.id for t in init_targets if t.id) + for i, target in enumerate(targets): + if (field._type == 'one2many' + and field.field +@@ -936,7 +936,7 @@ + try: + if target.id in previous: +- previous.remove(target.id) ++ previous.discard(target.id) + if isinstance(target, ModelView): + target_changed = target._changed_values() + if target_changed: diff --git a/defects/tryton-0001/test/TrytonChangedValuesTest.class b/defects/tryton-0001/test/TrytonChangedValuesTest.class new file mode 100644 index 000000000..c17a61358 Binary files /dev/null and b/defects/tryton-0001/test/TrytonChangedValuesTest.class differ diff --git a/defects/tryton-0001/test/TrytonChangedValuesTest.java b/defects/tryton-0001/test/TrytonChangedValuesTest.java new file mode 100644 index 000000000..6c37f2fc8 --- /dev/null +++ b/defects/tryton-0001/test/TrytonChangedValuesTest.java @@ -0,0 +1,100 @@ +import java.util.*; + +/** + * Unit test for Tryton CWE-407 defect: _changed_values and _save_values + * use list.remove(target.id) inside loop over targets, giving O(T*P) + * where T = number of targets in a one2many/many2many field and + * P = number of previous targets. + * + * Defect locations: + * trytond/model/modelview.py _changed_values() line ~925-937 + * trytond/model/modelstorage.py _save_values() line ~2118-2140 + * + * Fix: replace list with set for O(1) lookup and discard. + */ +public class TrytonChangedValuesTest { + + // --- DEFECTIVE: previous as List, O(T*P) --- + static long defectChangedValues(List previousIds, List targetIds) { + long ops = 0; + List previous = new ArrayList<>(previousIds); + for (int targetId : targetIds) { + // Simulate list.__contains__ scan + for (int j = 0; j < previous.size(); j++) { + ops++; + if (previous.get(j).equals(targetId)) break; + } + if (previous.contains(targetId)) { + previous.remove(Integer.valueOf(targetId)); + } + } + return ops; + } + + // --- FIXED: previous as Set, O(T) amortised --- + static long fixedChangedValues(List previousIds, List targetIds) { + long ops = 0; + Set previous = new HashSet<>(previousIds); + for (int targetId : targetIds) { + ops++; // O(1) hash lookup + if (previous.contains(targetId)) { + previous.remove(targetId); + } + } + return ops; + } + + public static void main(String[] args) { + int[] sizes = {100, 500, 1000}; + System.out.println("Tryton CWE-407: _changed_values / _save_values previous-list membership"); + System.out.println("T=targets P=previous defect_ops fixed_ops ratio"); + + boolean allPass = true; + for (int n : sizes) { + List previousIds = new ArrayList<>(); + List targetIds = new ArrayList<>(); + // Targets iterate in reverse order so each lookup must scan + // to the end of the shrinking previous list + for (int i = 0; i < n; i++) { + previousIds.add(i); + } + for (int i = n - 1; i >= 0; i--) { + targetIds.add(i); + } + + long defectOps = defectChangedValues(previousIds, targetIds); + long fixedOps = fixedChangedValues(previousIds, targetIds); + double ratio = (double) defectOps / fixedOps; + + System.out.printf("T=%-5d P=%-5d %10d %10d %8.1fx%n", + n, n, defectOps, fixedOps, ratio); + + if (ratio < 2.0) { + System.out.println("FAIL: ratio too low at N=" + n); + allPass = false; + } + } + + // Verify correctness: both produce same remaining set + List prev = Arrays.asList(1, 2, 3, 4, 5); + List tgts = Arrays.asList(2, 4); + + List prevList = new ArrayList<>(prev); + for (int t : tgts) { + if (prevList.contains(t)) prevList.remove(Integer.valueOf(t)); + } + + Set prevSet = new HashSet<>(prev); + for (int t : tgts) { + prevSet.remove(t); + } + + if (!new HashSet<>(prevList).equals(prevSet)) { + System.out.println("FAIL: correctness mismatch"); + allPass = false; + } + + System.out.println(allPass ? "PASS" : "FAIL"); + System.exit(allPass ? 0 : 1); + } +}