undf: assign UNDF-2026-000000874; stamp vllm-0001 patch

This commit is contained in:
russell@unturf.com 2026-03-30 16:42:12 -04:00
parent 80b26e82b6
commit 7e717432dd
196 changed files with 835 additions and 1 deletions

View file

@ -863,5 +863,14 @@
"erpnext-0001-0001": "UNDF-2026-000000862",
"erpnext-0002-0002": "UNDF-2026-000000863",
"ofbiz-0001-0001": "UNDF-2026-000000864",
"ofbiz-0002-0002": "UNDF-2026-000000865"
"ofbiz-0002-0002": "UNDF-2026-000000865",
"dolibarr-0001": "UNDF-2026-000000866",
"dolibarr-0002": "UNDF-2026-000000867",
"dolibarr-0003": "UNDF-2026-000000868",
"litellm-0001": "UNDF-2026-000000869",
"squid-0001-0001": "UNDF-2026-000000870",
"suitecrm-0001": "UNDF-2026-000000871",
"suitecrm-0002": "UNDF-2026-000000872",
"suitecrm-0003": "UNDF-2026-000000873",
"vllm-0001": "UNDF-2026-000000874"
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,14 @@
# UNDF: UNDF-2026-000000866
--- a/htdocs/blockedlog/admin/filecheck.php
+++ b/htdocs/blockedlog/admin/filecheck.php
@@ -409,9 +409,10 @@
// Complete with list of new files into $file_list['added']
if (empty($onlymodifiedorremoved)) {
+ $insignature_set = array_flip($file_list['insignature']); // O(1) lookup instead of O(N) in_array
foreach ($scanfiles as $valfile) {
$tmprelativefilename = preg_replace('/^'.preg_quote(DOL_DOCUMENT_ROOT, '/').'/', '', $valfile['fullname']);
- if (!in_array($tmprelativefilename, $file_list['insignature'])) {
+ if (!isset($insignature_set[$tmprelativefilename])) {
$hashnewfile = @hash_file($algo, $valfile['fullname']); // Can fails if we don't have permission to open/read file
$file_list['added'][] = array('filename' => $tmprelativefilename, 'hash' => $hashnewfile, 'algo' => $algo);
}

View file

@ -0,0 +1,28 @@
# UNDF: UNDF-2026-000000867
--- a/htdocs/datapolicy/class/datapolicycron.class.php
+++ b/htdocs/datapolicy/class/datapolicycron.class.php
@@ -335,6 +335,7 @@
* @param int[] $processedIds Reference to the array of processed IDs.
* @param object $conf The global conf object.
* @param User $user The user object for history tracking.
+ * Note: $processedIds is used as both array and set; callers should also pass $processedSet for O(1) lookup.
* @return void
*/
private function _processPolicyAction($policy, $action, $object, &$processedIds, $conf, $user)
@@ -367,7 +368,8 @@
// Process the records found by the query
+ $processedSet = array_flip($processedIds); // O(1) lookup instead of O(N) in_array
while ($obj = $this->db->fetch_object($resql)) {
- if (in_array($obj->rowid, $processedIds) || ! method_exists($this, $handlerMethod)) {
+ if (isset($processedSet[$obj->rowid]) || ! method_exists($this, $handlerMethod)) {
continue;
}
/** @var CommonObject $object */
@@ -383,6 +385,7 @@
// Record the outcome and add to processed list on success
$this->_recordActionResult($result, $object, $action);
$processedIds[] = $obj->rowid;
+ $processedSet[$obj->rowid] = true;
}
}

View file

@ -0,0 +1,20 @@
# UNDF: UNDF-2026-000000868
--- a/htdocs/accountancy/class/bookkeeping.class.php
+++ b/htdocs/accountancy/class/bookkeeping.class.php
@@ -3720,6 +3720,7 @@
$resqlAlreadyExtourne = $this->db->query($sqlAlreadyExtourne);
$alreadyExtourneT = array();
+ $alreadyExtourneSet = array(); // Hash set for O(1) lookup instead of O(N) in_array
if ($resqlAlreadyExtourne) {
while ($obj4 = $this->db->fetch_object($resqlAlreadyExtourne)) {
$alreadyExtourneT []= $obj4->piece_num;
+ $alreadyExtourneSet[$obj4->piece_num] = true;
}
}
@@ -3753,7 +3755,7 @@
if ($bookKeeping->fetch($extourneId)) {
- if (in_array($bookKeeping->piece_num, $alreadyExtourneT)) {
+ if (isset($alreadyExtourneSet[$bookKeeping->piece_num])) {
setEventMessages($langs->trans("AlreadyReturnedAccount", $bookKeeping->piece_num), null, 'errors');
} else {

Binary file not shown.

View file

@ -0,0 +1,217 @@
import java.util.*;
/**
* CWE-407 unit tests for Dolibarr defects.
*
* dolibarr-0001: filecheck.php in_array($tmprelativefilename, $file_list['insignature'])
* O(S*I) file membership check during integrity verification
* dolibarr-0002: datapolicycron.class.php in_array($obj->rowid, $processedIds)
* O(N^2) dedup accumulator in GDPR data policy cron
* dolibarr-0003: bookkeeping.class.php in_array($bookKeeping->piece_num, $alreadyExtourneT)
* O(P*E*A) reversal check in accounting journal extourne
*/
public class DolibarrCWE407Test {
// ---- dolibarr-0001: filecheck insignature membership ----
/** Unpatched: in_array on plain array — O(S*I) */
static int filecheckUnpatched(List<String> scanFiles, List<String> inSignature) {
List<String> added = new ArrayList<>();
for (String file : scanFiles) {
if (!inSignature.contains(file)) { // O(I) per file
added.add(file);
}
}
return added.size();
}
/** Patched: array_flip for O(1) lookup — O(S+I) */
static int filecheckPatched(List<String> scanFiles, List<String> inSignature) {
Set<String> sigSet = new HashSet<>(inSignature); // O(I) once
List<String> added = new ArrayList<>();
for (String file : scanFiles) {
if (!sigSet.contains(file)) { // O(1) per file
added.add(file);
}
}
return added.size();
}
// ---- dolibarr-0002: datapolicycron processedIds dedup ----
/** Unpatched: in_array on growing processedIds — O(N^2) */
static int datapolicyCronUnpatched(List<Integer> dbRows) {
List<Integer> processedIds = new ArrayList<>();
int processed = 0;
for (int rowid : dbRows) {
if (!processedIds.contains(rowid)) { // O(N) scan
processed++;
processedIds.add(rowid);
}
}
return processed;
}
/** Patched: array_flip for O(1) lookup — O(N) total */
static int datapolicyCronPatched(List<Integer> dbRows) {
Set<Integer> processedSet = new HashSet<>();
int processed = 0;
for (int rowid : dbRows) {
if (!processedSet.contains(rowid)) { // O(1) lookup
processed++;
processedSet.add(rowid);
}
}
return processed;
}
// ---- dolibarr-0003: bookkeeping extourne reversal check ----
/** Unpatched: in_array on alreadyExtourneT — O(P*E*A) */
static int extourneUnpatched(List<Integer> pieceNums, List<Integer> alreadyExtourne) {
int reversed = 0;
for (int pieceNum : pieceNums) {
// Inner loop simulates fetching entries per piece
for (int entry = 0; entry < 5; entry++) {
if (alreadyExtourne.contains(pieceNum)) { // O(A) scan
// already reversed skip
} else {
reversed++;
}
}
}
return reversed;
}
/** Patched: hash set for O(1) lookup — O(P*E + A) */
static int extournePatched(List<Integer> pieceNums, List<Integer> alreadyExtourne) {
Set<Integer> alreadySet = new HashSet<>(alreadyExtourne); // O(A) once
int reversed = 0;
for (int pieceNum : pieceNums) {
for (int entry = 0; entry < 5; entry++) {
if (alreadySet.contains(pieceNum)) { // O(1) lookup
// already reversed skip
} else {
reversed++;
}
}
}
return reversed;
}
// ---- Test harness ----
static void testDolibarr0001() {
System.out.println("=== dolibarr-0001: filecheck insignature membership ===");
int S = 16000; // scanned files (typical Dolibarr installation)
int I = 14000; // files in signature
List<String> scanFiles = new ArrayList<>(S);
List<String> inSignature = new ArrayList<>(I);
for (int i = 0; i < I; i++) {
String name = "/htdocs/module" + (i / 100) + "/file" + i + ".php";
inSignature.add(name);
scanFiles.add(name);
}
// Add some files not in signature
for (int i = I; i < S; i++) {
scanFiles.add("/htdocs/custom/file" + i + ".php");
}
// Warmup
filecheckPatched(scanFiles, inSignature);
long t0 = System.nanoTime();
int r1 = filecheckUnpatched(scanFiles, inSignature);
long unpatched = System.nanoTime() - t0;
t0 = System.nanoTime();
int r2 = filecheckPatched(scanFiles, inSignature);
long patched = System.nanoTime() - t0;
assert r1 == r2 : "Result mismatch";
assert r1 == (S - I) : "Expected " + (S - I) + " added files, got " + r1;
double ratio = (double) unpatched / patched;
System.out.printf(" S=%d I=%d unpatched=%dms patched=%dms ratio=%.1fx%n",
S, I, unpatched / 1_000_000, patched / 1_000_000, ratio);
assert ratio > 5.0 : "Expected >5x ratio, got " + ratio;
System.out.println(" PASS");
}
static void testDolibarr0002() {
System.out.println("=== dolibarr-0002: datapolicycron processedIds dedup ===");
int N = 10000; // GDPR records to process
List<Integer> dbRows = new ArrayList<>(N);
for (int i = 0; i < N; i++) {
dbRows.add(i);
}
// Add some duplicates
for (int i = 0; i < N / 10; i++) {
dbRows.add(i);
}
// Warmup
datapolicyCronPatched(dbRows);
long t0 = System.nanoTime();
int r1 = datapolicyCronUnpatched(dbRows);
long unpatched = System.nanoTime() - t0;
t0 = System.nanoTime();
int r2 = datapolicyCronPatched(dbRows);
long patched = System.nanoTime() - t0;
assert r1 == r2 : "Result mismatch";
assert r1 == N : "Expected " + N + " unique, got " + r1;
double ratio = (double) unpatched / patched;
System.out.printf(" N=%d unpatched=%dms patched=%dms ratio=%.1fx%n",
N, unpatched / 1_000_000, patched / 1_000_000, ratio);
assert ratio > 5.0 : "Expected >5x ratio, got " + ratio;
System.out.println(" PASS");
}
static void testDolibarr0003() {
System.out.println("=== dolibarr-0003: bookkeeping extourne reversal check ===");
int P = 2000; // pieces to reverse
int A = 5000; // already-reversed pieces
List<Integer> pieceNums = new ArrayList<>(P);
for (int i = 0; i < P; i++) {
pieceNums.add(A + i); // new pieces not in already-reversed set
}
List<Integer> alreadyExtourne = new ArrayList<>(A);
for (int i = 0; i < A; i++) {
alreadyExtourne.add(i);
}
// Warmup
extournePatched(pieceNums, alreadyExtourne);
long t0 = System.nanoTime();
int r1 = extourneUnpatched(pieceNums, alreadyExtourne);
long unpatched = System.nanoTime() - t0;
t0 = System.nanoTime();
int r2 = extournePatched(pieceNums, alreadyExtourne);
long patched = System.nanoTime() - t0;
assert r1 == r2 : "Result mismatch";
assert r1 == P * 5 : "Expected " + (P * 5) + " reversed, got " + r1;
double ratio = (double) unpatched / patched;
System.out.printf(" P=%d A=%d unpatched=%dms patched=%dms ratio=%.1fx%n",
P, A, unpatched / 1_000_000, patched / 1_000_000, ratio);
assert ratio > 5.0 : "Expected >5x ratio, got " + ratio;
System.out.println(" PASS");
}
public static void main(String[] args) {
testDolibarr0001();
testDolibarr0002();
testDolibarr0003();
System.out.println("\nAll 3 Dolibarr CWE-407 tests PASSED.");
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,14 @@
# UNDF: UNDF-2026-000000869
--- a/litellm/proxy/proxy_server.py
+++ b/litellm/proxy/proxy_server.py
@@ -3876,8 +3876,9 @@ class ProxyConfig:
router_model_ids = llm_router.get_model_ids()
# Check for model IDs in llm_router not present in combined_id_list and delete them
+ combined_id_set = set(combined_id_list) # O(1) lookup instead of O(N) list scan
deleted_deployments = 0
for model_id in router_model_ids:
- if model_id not in combined_id_list:
+ if model_id not in combined_id_set:
is_deleted = llm_router.delete_deployment(id=model_id)
if is_deleted is not None:

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show more