From 364094f3d961751c5482f6ea36feff1965fee6af Mon Sep 17 00:00:00 2001
From: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Date: Mon, 30 Mar 2026 08:14:05 +0000
Subject: [PATCH] perf/fix: clamp minSubstringLength≥1 and precompute lowercase strings in containsSubstring

---
 opendj-server-legacy/src/main/java/org/opends/server/extensions/AttributeValuePasswordValidator.java |   21 +++++++++++++++++----
 1 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/server/extensions/AttributeValuePasswordValidator.java b/opendj-server-legacy/src/main/java/org/opends/server/extensions/AttributeValuePasswordValidator.java
index a724595..e27fbb7 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/extensions/AttributeValuePasswordValidator.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/extensions/AttributeValuePasswordValidator.java
@@ -19,6 +19,7 @@
 
 import org.forgerock.i18n.LocalizableMessage;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
 import java.util.Set;
@@ -83,16 +84,28 @@
   private boolean containsSubstring(String password, int minSubstringLength,
       Attribute a)
   {
+    // Clamp to at least 1 so an empty substring never matches unconditionally.
+    final int minLen = Math.max(1, minSubstringLength);
     final int passwordLength = password.length();
 
+    // Precompute the lowercase password once to avoid repeated conversions.
+    final String passwordLower = password.toLowerCase(Locale.ROOT);
+
+    // Precompute lowercase attribute values once, outside the substring loops.
+    final List<String> attrValuesLower = new ArrayList<>(a.size());
+    for (ByteString val : a)
+    {
+      attrValuesLower.add(val.toString().toLowerCase(Locale.ROOT));
+    }
+
     for (int i = 0; i < passwordLength; i++)
     {
-      for (int j = i + minSubstringLength; j <= passwordLength; j++)
+      for (int j = i + minLen; j <= passwordLength; j++)
       {
-        final String pwdSubstring = password.substring(i, j).toLowerCase(Locale.ROOT);
-        for (ByteString val : a)
+        final String pwdSubstring = passwordLower.substring(i, j);
+        for (String attrValueLower : attrValuesLower)
         {
-          if (val.toString().toLowerCase(Locale.ROOT).contains(pwdSubstring))
+          if (attrValueLower.contains(pwdSubstring))
           {
             return true;
           }

--
Gitblit v1.10.0