From e24c2780b6d44c7e5d386e70a1fb3346149ccdc9 Mon Sep 17 00:00:00 2001
From: Valery Kharseko <vharseko@3a-systems.ru>
Date: Tue, 04 Aug 2026 07:15:33 +0000
Subject: [PATCH] Fix CodeQL note-severity alerts: array logging and uncaught NumberFormatException (#817)

---
 opendj-server-legacy/src/main/java/org/opends/server/replication/common/CSN.java                                   |   27 +++-
 opendj-core/src/main/java/org/forgerock/opendj/ldap/MemoryBackend.java                                             |   29 ++++
 opendj-core/src/main/java/org/forgerock/opendj/ldap/GSERParser.java                                                |    9 +
 opendj-server-legacy/src/test/java/org/opends/server/replication/common/CSNTest.java                               |   23 +++
 opendj-core/src/test/java/org/forgerock/opendj/ldap/MemoryBackendTestCase.java                                     |   17 ++
 opendj-server-legacy/src/main/java/org/opends/server/replication/server/changelog/file/FileReplicaDB.java          |   12 +
 opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/ID2ChildrenCount.java                      |    3 
 opendj-server-legacy/src/main/java/org/opends/server/backends/ChangelogBackend.java                                |   16 ++
 opendj-server-legacy/src/main/java/org/opends/server/backends/jdbc/CachedConnection.java                           |   31 ++++
 opendj-server-legacy/src/test/java/org/opends/server/replication/protocol/ByteArrayTest.java                       |    8 +
 opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/browser/BrowserController.java                 |    3 
 opendj-server-legacy/src/main/java/org/opends/server/replication/server/changelog/file/ReplicationEnvironment.java |   19 ++
 opendj-server-legacy/src/main/java/org/opends/server/util/BackupManager.java                                       |   46 +++++++
 opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/ID2Entry.java                              |   26 ++++
 opendj-server-legacy/src/main/java/org/opends/server/schema/GeneralizedTimeSyntax.java                             |    6 
 opendj-server-legacy/src/main/java/org/opends/server/types/HostPort.java                                           |    7 
 opendj-server-legacy/src/main/java/org/opends/server/util/SchemaUtils.java                                         |   12 +
 opendj-server-legacy/src/main/java/org/opends/server/core/PasswordPolicyState.java                                 |    4 
 opendj-server-legacy/src/main/java/org/opends/server/protocols/asn1/GSERParser.java                                |   12 +
 opendj-server-legacy/src/main/java/org/opends/server/types/SubtreeSpecification.java                               |   10 +
 opendj-server-legacy/src/main/java/org/opends/server/replication/protocol/ByteArrayScanner.java                    |   23 +++
 opendj-core/src/test/java/org/forgerock/opendj/ldap/GSERParserTestCase.java                                        |    5 
 opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/ImportLDIFReader.java                      |    3 
 23 files changed, 312 insertions(+), 39 deletions(-)

diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/GSERParser.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/GSERParser.java
index 0643b5d..60b6bd8 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/GSERParser.java
+++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/GSERParser.java
@@ -12,6 +12,7 @@
  * information: "Portions Copyright [year] [name of copyright owner]".
  *
  * Copyright 2013-2014 Manuel Gaupp
+ * Portions Copyright 2026 3A Systems, LLC.
  */
 package org.forgerock.opendj.ldap;
 
@@ -321,7 +322,13 @@
                     WARN_GSER_NO_VALID_INTEGER.get(gserValue.substring(pos, length));
             throw DecodeException.error(msg);
         }
-        return Integer.valueOf(next(GSER_INTEGER)).intValue();
+        final String integer = next(GSER_INTEGER);
+        try {
+            return Integer.parseInt(integer);
+        } catch (final NumberFormatException e) {
+            // The value matches the integer pattern but does not fit in an int.
+            throw DecodeException.error(WARN_GSER_NO_VALID_INTEGER.get(integer), e);
+        }
     }
 
     /**
diff --git a/opendj-core/src/main/java/org/forgerock/opendj/ldap/MemoryBackend.java b/opendj-core/src/main/java/org/forgerock/opendj/ldap/MemoryBackend.java
index 3060bc1..b5605c6 100644
--- a/opendj-core/src/main/java/org/forgerock/opendj/ldap/MemoryBackend.java
+++ b/opendj-core/src/main/java/org/forgerock/opendj/ldap/MemoryBackend.java
@@ -12,6 +12,7 @@
  * information: "Portions Copyright [year] [name of copyright owner]".
  *
  * Copyright 2013-2016 ForgeRock AS.
+ * Portions Copyright 2026 3A Systems, LLC.
  */
 package org.forgerock.opendj.ldap;
 
@@ -580,8 +581,7 @@
         }
 
         final int pageSize = pagedResults != null ? pagedResults.getSize() : 0;
-        final int offset = (pagedResults != null && !pagedResults.getCookie().isEmpty())
-                ? Integer.valueOf(pagedResults.getCookie().toString()) : 0;
+        final int offset = decodePagedResultsCookie(pagedResults);
         int numberOfResults = 0;
         int position = 0;
         for (final Entry entry : subtree.values()) {
@@ -630,6 +630,31 @@
         resultHandler.handleResult(result);
     }
 
+    /**
+     * Returns the offset of the first entry to be returned, as encoded by this backend in the cookie
+     * of the previous page.
+     *
+     * @param pagedResults
+     *            The simple paged results control, if present.
+     * @return The offset of the first entry to be returned.
+     * @throws LdapException
+     *             If the cookie was not created by this backend.
+     */
+    private static int decodePagedResultsCookie(final SimplePagedResultsControl pagedResults) throws LdapException {
+        if (pagedResults == null || pagedResults.getCookie().isEmpty()) {
+            return 0;
+        }
+        final String cookie = pagedResults.getCookie().toString();
+        try {
+            return Integer.parseInt(cookie);
+        } catch (final NumberFormatException e) {
+            throw newLdapException(newResult(ResultCode.PROTOCOL_ERROR)
+                    .setDiagnosticMessage(
+                            "Invalid paged results cookie: " + pagedResults.getCookie().toHexString())
+                    .setCause(e));
+        }
+    }
+
     private <R extends Result> R addResultControls(final Request request, final Entry before,
             final Entry after, final R result) throws LdapException {
         try {
diff --git a/opendj-core/src/test/java/org/forgerock/opendj/ldap/GSERParserTestCase.java b/opendj-core/src/test/java/org/forgerock/opendj/ldap/GSERParserTestCase.java
index 5b63103..67e59a1 100644
--- a/opendj-core/src/test/java/org/forgerock/opendj/ldap/GSERParserTestCase.java
+++ b/opendj-core/src/test/java/org/forgerock/opendj/ldap/GSERParserTestCase.java
@@ -12,6 +12,7 @@
  * information: "Portions Copyright [year] [name of copyright owner]".
  *
  * Copyright 2013-2014 Manuel Gaupp
+ * Portions Copyright 2026 3A Systems, LLC.
  */
 package org.forgerock.opendj.ldap;
 
@@ -165,7 +166,9 @@
             {"", false},
             {"0xFF", false},
             {"NULL", false},
-            {"Not a Number", false}
+            {"Not a Number", false},
+            {"2147483648", false},
+            {"99999999999", false}
         };
     }
 
diff --git a/opendj-core/src/test/java/org/forgerock/opendj/ldap/MemoryBackendTestCase.java b/opendj-core/src/test/java/org/forgerock/opendj/ldap/MemoryBackendTestCase.java
index ef9ffd0..6304de5 100644
--- a/opendj-core/src/test/java/org/forgerock/opendj/ldap/MemoryBackendTestCase.java
+++ b/opendj-core/src/test/java/org/forgerock/opendj/ldap/MemoryBackendTestCase.java
@@ -12,6 +12,7 @@
  * information: "Portions Copyright [year] [name of copyright owner]".
  *
  * Copyright 2013-2016 ForgeRock AS.
+ * Portions Copyright 2026 3A Systems, LLC.
  */
 package org.forgerock.opendj.ldap;
 
@@ -549,6 +550,22 @@
     }
 
     @Test
+    public void testSearchPagedResultsForgedCookie() throws Exception {
+        final Connection connection = getConnection();
+        final SearchRequest search =
+                Requests.newSearchRequest("ou=people,dc=example,dc=com", SearchScope.WHOLE_SUBTREE,
+                        "(uid=*)");
+        search.addControl(
+                SimplePagedResultsControl.newControl(true, 2, ByteString.valueOfUtf8("forged")));
+        try {
+            connection.search(search, new ArrayList<SearchResultEntry>());
+            TestCaseUtils.failWasExpected(LdapException.class);
+        } catch (LdapException e) {
+            assertThat(e.getResult().getResultCode()).isEqualTo(ResultCode.PROTOCOL_ERROR);
+        }
+    }
+
+    @Test
     public void testSimpleBind() throws Exception {
         final Connection connection = getConnection();
         connection.bind("uid=test1,ou=people,dc=example,dc=com", "password".toCharArray());
diff --git a/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/browser/BrowserController.java b/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/browser/BrowserController.java
index edfc629..f3c0ab9 100644
--- a/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/browser/BrowserController.java
+++ b/opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/browser/BrowserController.java
@@ -23,6 +23,7 @@
 import java.awt.Font;
 import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Enumeration;
 import java.util.Set;
@@ -1838,7 +1839,7 @@
       sb.append(getURL());
       if (getReferral() != null) {
         sb.append(" -> ");
-        sb.append(getReferral());
+        sb.append(Arrays.toString(getReferral()));
       }
       toString = sb.toString();
     }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/ChangelogBackend.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/ChangelogBackend.java
index b899eb3..ec10c37 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/ChangelogBackend.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/ChangelogBackend.java
@@ -753,7 +753,7 @@
     {
       // == exact CSN
       // validate provided CSN is correct
-      new CSN(filter.getAssertionValue().toString());
+      validateCSN(filter.getAssertionValue());
     }
     else if (filter.getFilterType() == FilterType.AND)
     {
@@ -808,6 +808,20 @@
     }
   }
 
+  private static void validateCSN(final ByteString assertionValue)
+      throws DirectoryException
+  {
+    try
+    {
+      new CSN(assertionValue.toString());
+    }
+    catch (IllegalArgumentException e)
+    {
+      throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX,
+          LocalizableMessage.raw("Could not convert value '%s' to a CSN", assertionValue), e);
+    }
+  }
+
   private boolean matches(SearchFilter filter, FilterType filterType, String primaryName)
   {
     return filter.getFilterType() == filterType
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/jdbc/CachedConnection.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/jdbc/CachedConnection.java
index 7d36e4e..f752ca5 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/jdbc/CachedConnection.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/jdbc/CachedConnection.java
@@ -11,13 +11,15 @@
  * Header, with the fields enclosed by brackets [] replaced by your own identifying
  * information: "Portions Copyright [year] [name of copyright owner]".
  *
- * Copyright 2024-2025 3A Systems, LLC.
+ * Copyright 2024-2026 3A Systems, LLC.
  */
 package org.opends.server.backends.jdbc;
 
 import com.github.benmanes.caffeine.cache.Caffeine;
 import com.github.benmanes.caffeine.cache.LoadingCache;
 import com.github.benmanes.caffeine.cache.RemovalCause;
+import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.i18n.slf4j.LocalizedLogger;
 
 import java.sql.*;
 import java.time.Duration;
@@ -26,10 +28,15 @@
 import java.util.concurrent.*;
 
 public class CachedConnection implements Connection {
+    private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
+
+    static final String TTL_PROPERTY = "org.openidentityplatform.opendj.jdbc.ttl";
+    static final long DEFAULT_TTL_MS = 15000;
+
     final Connection parent;
 
     static LoadingCache<String, BlockingQueue<CachedConnection>> cached = Caffeine.newBuilder()
-        .expireAfterAccess(Duration.ofMillis(Long.parseLong(System.getProperty("org.openidentityplatform.opendj.jdbc.ttl","15000"))))
+        .expireAfterAccess(Duration.ofMillis(getCacheTtlMillis()))
         .removalListener((String key, BlockingQueue<CachedConnection> value, RemovalCause cause) -> {
             for (CachedConnection con : value) {
                 try {
@@ -43,6 +50,26 @@
         })
         .build(conStr -> new LinkedBlockingQueue<>());
 
+    /**
+     * Returns the time after which an idle pooled connection is closed, as configured by the
+     * {@value #TTL_PROPERTY} system property. An invalid value is ignored in favor of the default.
+     */
+    private static long getCacheTtlMillis() {
+        final String ttl = System.getProperty(TTL_PROPERTY);
+        if (ttl != null) {
+            try {
+                final long millis = Long.parseLong(ttl.trim());
+                if (millis >= 0) {
+                    return millis;
+                }
+            } catch (NumberFormatException ignored) {
+            }
+            logger.warn(LocalizableMessage.raw("Ignoring invalid value \"%s\" of the %s property, using %d ms",
+                ttl, TTL_PROPERTY, DEFAULT_TTL_MS));
+        }
+        return DEFAULT_TTL_MS;
+    }
+
     final String connectionString;
     public CachedConnection(String connectionString, Connection parent) {
         this.connectionString = connectionString;
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/ID2ChildrenCount.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/ID2ChildrenCount.java
index dd57bea..812300f 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/ID2ChildrenCount.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/ID2ChildrenCount.java
@@ -12,6 +12,7 @@
  * information: "Portions Copyright [year] [name of copyright owner]".
  *
  * Copyright 2015 ForgeRock AS.
+ * Portions Copyright 2026 3A Systems, LLC.
  */
 package org.opends.server.backends.pluggable;
 
@@ -129,7 +130,7 @@
   @Override
   public ByteString generateKey(String data)
   {
-    return new EntryID(Long.parseLong(data)).toByteString();
+    return new EntryID(ID2Entry.parseEntryID(data)).toByteString();
   }
 
   /**
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/ID2Entry.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/ID2Entry.java
index be1fd64..72bbded 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/ID2Entry.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/ID2Entry.java
@@ -32,6 +32,8 @@
 import java.util.zip.InflaterInputStream;
 import java.util.zip.InflaterOutputStream;
 
+import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.i18n.LocalizedIllegalArgumentException;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
 import org.forgerock.opendj.io.ASN1;
 import org.forgerock.opendj.io.ASN1Reader;
@@ -556,7 +558,27 @@
   @Override
   public ByteString generateKey(String data)
   {
-    EntryID entryID = new EntryID(Long.parseLong(data));
-    return entryID.toByteString();
+    return new EntryID(parseEntryID(data)).toByteString();
+  }
+
+  /**
+   * Returns the entry ID held by the provided string.
+   *
+   * @param data
+   *          The string representation of an entry ID
+   * @return the parsed entry ID
+   * @throws LocalizedIllegalArgumentException
+   *           If the provided string does not hold an entry ID
+   */
+  static long parseEntryID(String data)
+  {
+    try
+    {
+      return Long.parseLong(data);
+    }
+    catch (NumberFormatException e)
+    {
+      throw new LocalizedIllegalArgumentException(LocalizableMessage.raw("Invalid entry ID: \"%s\"", data));
+    }
   }
 }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/ImportLDIFReader.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/ImportLDIFReader.java
index cb553f4..71ff855 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/ImportLDIFReader.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/ImportLDIFReader.java
@@ -12,6 +12,7 @@
  * information: "Portions Copyright [year] [name of copyright owner]".
  *
  * Copyright 2015-2016 ForgeRock AS.
+ * Portions Copyright 2026 3A Systems, LLC.
  */
 package org.opends.server.backends.pluggable;
 
@@ -211,7 +212,7 @@
     {
       if (logger.isTraceEnabled())
       {
-        logger.trace("Skipping entry %s because reading" + "its attributes failed.", entryDN);
+        logger.trace("Skipping entry %s because reading its attributes failed.", entryDN);
       }
       logToSkipWriter(lines, ERR_LDIF_READ_ATTR_SKIP.get(entryDN, e.getMessage()));
       return null;
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/core/PasswordPolicyState.java b/opendj-server-legacy/src/main/java/org/opends/server/core/PasswordPolicyState.java
index 4998dab..8fa24e0 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/core/PasswordPolicyState.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/core/PasswordPolicyState.java
@@ -2700,8 +2700,8 @@
     {
       if (logger.isTraceEnabled())
       {
-        logger.trace("Unable to generate a new password for user %s because no password generator has been defined" +
-            "in the associated password policy.", userDNString);
+        logger.trace("Unable to generate a new password for user %s because no password generator has been defined "
+            + "in the associated password policy.", userDNString);
       }
 
       return null;
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/protocols/asn1/GSERParser.java b/opendj-server-legacy/src/main/java/org/opends/server/protocols/asn1/GSERParser.java
index a43494a..92ba2f9 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/protocols/asn1/GSERParser.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/protocols/asn1/GSERParser.java
@@ -13,6 +13,7 @@
  *
  * Copyright 2013-2014 Manuel Gaupp
  * Portions Copyright 2014-2016 ForgeRock AS.
+ * Portions Copyright 2026 3A Systems, LLC.
  */
 package org.opends.server.protocols.asn1;
 
@@ -382,7 +383,16 @@
                       .substring(pos,length));
       throw new GSERException(msg);
     }
-    return Integer.valueOf(next(GSER_INTEGER)).intValue();
+    final String integer = next(GSER_INTEGER);
+    try
+    {
+      return Integer.parseInt(integer);
+    }
+    catch (NumberFormatException e)
+    {
+      // The value matches the integer pattern but does not fit in an int.
+      throw new GSERException(ERR_GSER_NO_VALID_INTEGER.get(integer), e);
+    }
   }
 
 
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/replication/common/CSN.java b/opendj-server-legacy/src/main/java/org/opends/server/replication/common/CSN.java
index 0026223..fc1fdcd 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/replication/common/CSN.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/replication/common/CSN.java
@@ -20,6 +20,8 @@
 import java.io.Serializable;
 import java.util.Date;
 
+import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.i18n.LocalizedIllegalArgumentException;
 import org.forgerock.opendj.ldap.ByteSequence;
 import org.forgerock.opendj.ldap.ByteSequenceReader;
 import org.forgerock.opendj.ldap.ByteString;
@@ -72,6 +74,8 @@
    * @param s
    *          The string to be parsed.
    * @return The parsed CSN.
+   * @throws LocalizedIllegalArgumentException
+   *           If the provided string is not a valid {@link #toString()} representation of a CSN
    * @see #toString()
    */
   public static CSN valueOf(String s)
@@ -102,17 +106,26 @@
    *
    * @param str
    *          the string from which to create a {@link CSN}
+   * @throws LocalizedIllegalArgumentException
+   *           If the provided string is not a valid {@link #toString()} representation of a CSN
    */
   public CSN(String str)
   {
-    String temp = str.substring(0, 16);
-    timeStamp = Long.parseLong(temp, 16);
+    if (str == null || str.length() < STRING_ENCODING_LENGTH)
+    {
+      throw new LocalizedIllegalArgumentException(LocalizableMessage.raw("Invalid CSN: \"%s\"", str));
+    }
 
-    temp = str.substring(16, 20);
-    serverId = Integer.parseInt(temp, 16);
-
-    temp = str.substring(20, 28);
-    seqnum = Integer.parseInt(temp, 16);
+    try
+    {
+      timeStamp = Long.parseLong(str.substring(0, 16), 16);
+      serverId = Integer.parseInt(str.substring(16, 20), 16);
+      seqnum = Integer.parseInt(str.substring(20, STRING_ENCODING_LENGTH), 16);
+    }
+    catch (NumberFormatException e)
+    {
+      throw new LocalizedIllegalArgumentException(LocalizableMessage.raw("Invalid CSN: \"%s\"", str));
+    }
   }
 
   /**
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/replication/protocol/ByteArrayScanner.java b/opendj-server-legacy/src/main/java/org/opends/server/replication/protocol/ByteArrayScanner.java
index 91a3976..6d09850 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/replication/protocol/ByteArrayScanner.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/replication/protocol/ByteArrayScanner.java
@@ -12,6 +12,7 @@
  * information: "Portions Copyright [year] [name of copyright owner]".
  *
  * Copyright 2014-2016 ForgeRock AS.
+ * Portions Copyright 2026 3A Systems, LLC.
  */
 package org.opends.server.replication.protocol;
 
@@ -152,7 +153,15 @@
    */
   public int nextIntUTF8() throws DataFormatException
   {
-    return Integer.valueOf(nextString());
+    final String s = nextString();
+    try
+    {
+      return Integer.parseInt(s);
+    }
+    catch (NumberFormatException e)
+    {
+      throw new DataFormatException("Expected an int but read \"" + s + "\"");
+    }
   }
 
   /**
@@ -164,7 +173,15 @@
    */
   public long nextLongUTF8() throws DataFormatException
   {
-    return Long.valueOf(nextString());
+    final String s = nextString();
+    try
+    {
+      return Long.parseLong(s);
+    }
+    catch (NumberFormatException e)
+    {
+      throw new DataFormatException("Expected a long but read \"" + s + "\"");
+    }
   }
 
   /**
@@ -267,7 +284,7 @@
     {
       return CSN.valueOf(nextString());
     }
-    catch (IndexOutOfBoundsException e)
+    catch (LocalizedIllegalArgumentException | IndexOutOfBoundsException e)
     {
       throw new DataFormatException(e.getMessage());
     }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/replication/server/changelog/file/FileReplicaDB.java b/opendj-server-legacy/src/main/java/org/opends/server/replication/server/changelog/file/FileReplicaDB.java
index 709b87e..ac4ec81 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/replication/server/changelog/file/FileReplicaDB.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/replication/server/changelog/file/FileReplicaDB.java
@@ -12,6 +12,7 @@
  * information: "Portions Copyright [year] [name of copyright owner]".
  *
  * Copyright 2014-2016 ForgeRock AS.
+ * Portions Copyright 2026 3A Systems, LLC.
  */
 package org.opends.server.replication.server.changelog.file;
 
@@ -25,6 +26,7 @@
 
 import net.jcip.annotations.Immutable;
 
+import org.forgerock.i18n.LocalizedIllegalArgumentException;
 import org.forgerock.opendj.config.server.ConfigException;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ByteStringBuilder;
@@ -415,7 +417,15 @@
     @Override
     public CSN decodeKeyFromString(String key) throws ChangelogException
     {
-      return new CSN(key);
+      try
+      {
+        return new CSN(key);
+      }
+      catch (LocalizedIllegalArgumentException e)
+      {
+        throw new ChangelogException(
+            ERR_CHANGELOG_UNABLE_TO_DECODE_KEY_FROM_STRING.get(key), e);
+      }
     }
 
     @Override
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/replication/server/changelog/file/ReplicationEnvironment.java b/opendj-server-legacy/src/main/java/org/opends/server/replication/server/changelog/file/ReplicationEnvironment.java
index d52eb2a..ee1282c 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/replication/server/changelog/file/ReplicationEnvironment.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/replication/server/changelog/file/ReplicationEnvironment.java
@@ -12,6 +12,7 @@
  * information: "Portions Copyright [year] [name of copyright owner]".
  *
  * Copyright 2014-2016 ForgeRock AS.
+ * Portions Copyright 2026 3A Systems, LLC.
  */
 package org.opends.server.replication.server.changelog.file;
 
@@ -698,6 +699,11 @@
       }
       return new CSN(line);
     }
+    catch(LocalizedIllegalArgumentException e)
+    {
+      throw new ChangelogException(ERR_CHANGELOG_INVALID_REPLICA_OFFLINE_STATE_FILE.get(
+          domainDN.toString(), offlineFile.getPath()), e);
+    }
     catch(IOException e)
     {
       throw new ChangelogException(ERR_CHANGELOG_UNABLE_TO_READ_REPLICA_OFFLINE_STATE_FILE.get(
@@ -731,12 +737,21 @@
   }
 
   /** Find the next domain id to use. This is the lowest integer that is higher than all existing ids. */
-  private String findNextDomainId()
+  private String findNextDomainId() throws ChangelogException
   {
     int nextId = 1;
     for (final String domainId : domains.values())
     {
-      final Integer id = Integer.valueOf(domainId);
+      final int id;
+      try
+      {
+        id = Integer.parseInt(domainId);
+      }
+      catch (NumberFormatException e)
+      {
+        throw new ChangelogException(ERR_CHANGELOG_UNABLE_TO_READ_DOMAIN_STATE_FILE.get(
+            new File(replicationRootPath, DOMAINS_STATE_FILENAME).getPath()), e);
+      }
       if (nextId <= id)
       {
         nextId = id + 1;
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/schema/GeneralizedTimeSyntax.java b/opendj-server-legacy/src/main/java/org/opends/server/schema/GeneralizedTimeSyntax.java
index 075f539..08a9581 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/schema/GeneralizedTimeSyntax.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/schema/GeneralizedTimeSyntax.java
@@ -1200,11 +1200,11 @@
               ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
     }
 
-    double fractionValue = Double.parseDouble(fractionBuffer.toString());
-    long additionalMilliseconds = Math.round(fractionValue * multiplier);
-
     try
     {
+      double fractionValue = Double.parseDouble(fractionBuffer.toString());
+      long additionalMilliseconds = Math.round(fractionValue * multiplier);
+
       GregorianCalendar calendar = new GregorianCalendar();
       calendar.setLenient(false);
       calendar.setTimeZone(timeZone);
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/types/HostPort.java b/opendj-server-legacy/src/main/java/org/opends/server/types/HostPort.java
index bff0143..7f3c746 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/types/HostPort.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/types/HostPort.java
@@ -24,6 +24,7 @@
 import java.net.NetworkInterface;
 import java.net.SocketException;
 import java.net.UnknownHostException;
+import java.util.Arrays;
 import java.util.Enumeration;
 import java.util.HashSet;
 import java.util.Locale;
@@ -497,7 +498,8 @@
       else if (thisAddresses == null || otherAddresses == null)
       {
         if(logger.isTraceEnabled()) {
-          logger.trace("port and host does not match: " + this + "=" + thisAddresses + "; " + other + "=" + otherAddresses);
+          logger.trace("port and host does not match: " + this + "=" + Arrays.toString(thisAddresses)
+              + "; " + other + "=" + Arrays.toString(otherAddresses));
         }
         // One local address and one non-local.
         return false;
@@ -515,7 +517,8 @@
         }
       }
       if(logger.isTraceEnabled()) {
-        logger.trace("port and host does not match: " + this + "=" + thisAddresses + "; " + other + "=" + otherAddresses);
+        logger.trace("port and host does not match: " + this + "=" + Arrays.toString(thisAddresses)
+            + "; " + other + "=" + Arrays.toString(otherAddresses));
       }
 
       return false;
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/types/SubtreeSpecification.java b/opendj-server-legacy/src/main/java/org/opends/server/types/SubtreeSpecification.java
index fc4f60d..7ff72f4 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/types/SubtreeSpecification.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/types/SubtreeSpecification.java
@@ -568,7 +568,15 @@
         NoSuchElementException
     {
       final String s = nextValue(INT, INT_TOKEN);
-      return Integer.parseInt(s);
+      try
+      {
+        return Integer.parseInt(s);
+      }
+      catch (NumberFormatException e)
+      {
+        // The token matches the integer pattern but is too big to fit in an int.
+        throw new InputMismatchException();
+      }
     }
 
     /**
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/util/BackupManager.java b/opendj-server-legacy/src/main/java/org/opends/server/util/BackupManager.java
index 98f3522..8eb09b4 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/util/BackupManager.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/util/BackupManager.java
@@ -20,6 +20,7 @@
 import static java.util.Collections.*;
 
 import static org.opends.messages.BackendMessages.*;
+import static org.opends.messages.CoreMessages.ERR_BACKUPINFO_CANNOT_DECODE;
 import static org.opends.messages.UtilityMessages.*;
 import static org.opends.server.util.ServerConstants.*;
 import static org.opends.server.util.StaticUtils.*;
@@ -515,7 +516,7 @@
     private final NewBackupParams newBackupParams;
     private final CryptoEngine cryptoEngine;
 
-    NewBackupArchive(String backendID, NewBackupParams backupParams, CryptoEngine crypt)
+    NewBackupArchive(String backendID, NewBackupParams backupParams, CryptoEngine crypt) throws DirectoryException
     {
       this.backendID = backendID;
       this.newBackupParams = backupParams;
@@ -525,11 +526,26 @@
       {
         Map<String, String> properties = backupParams.baseBackupInfo.getBackupProperties();
         latestFileName = properties.get(PROPERTY_LAST_LOGFILE_NAME);
-        latestFileSize = Long.parseLong(properties.get(PROPERTY_LAST_LOGFILE_SIZE));
+        latestFileSize = parseLatestFileSize(backupParams, properties.get(PROPERTY_LAST_LOGFILE_SIZE));
       }
       archiveFilename = BACKUP_BASE_FILENAME + backendID + "-" +  backupParams.backupID;
     }
 
+    /** Returns the size recorded by the base backup for the last file it archived. */
+    private static long parseLatestFileSize(NewBackupParams backupParams, String size) throws DirectoryException
+    {
+      try
+      {
+        return Long.parseLong(size);
+      }
+      catch (NumberFormatException e)
+      {
+        throw new DirectoryException(DirectoryServer.getCoreConfigManager().getServerErrorResultCode(),
+            ERR_BACKUPINFO_CANNOT_DECODE.get(backupParams.backupDir.getPath(),
+                PROPERTY_LAST_LOGFILE_SIZE + ": " + size), e);
+      }
+    }
+
     String getArchiveFilename()
     {
       return archiveFilename;
@@ -1553,7 +1569,7 @@
   {
     final File baseFile = new File(basePath).getCanonicalFile();
     final File[] existingFiles = baseFile.getParentFile().listFiles();
-    final Pattern pattern = Pattern.compile(baseFile + "\\d*");
+    final Pattern pattern = Pattern.compile(Pattern.quote(baseFile.getPath()) + "\\d*");
     int highestNumber = 0;
     for (File file : existingFiles)
     {
@@ -1561,10 +1577,32 @@
       if (pattern.matcher(name).matches())
       {
         String numberAsString = name.substring(baseFile.getPath().length());
-        int number = numberAsString.isEmpty() ? 0 : Integer.valueOf(numberAsString);
+        int number = parseSuffixNumber(numberAsString);
         highestNumber = number > highestNumber ? number : highestNumber;
       }
     }
     return highestNumber;
   }
+
+  /**
+   * Returns the number held by the provided file name suffix, or 0 if the suffix is empty or holds a
+   * number which is too big to have been generated by this class.
+   */
+  private static int parseSuffixNumber(final String numberAsString)
+  {
+    if (numberAsString.isEmpty())
+    {
+      return 0;
+    }
+    try
+    {
+      return Integer.parseInt(numberAsString);
+    }
+    catch (NumberFormatException e)
+    {
+      logger.trace("Ignoring file suffix \"%s\" which is too big to have been generated by this class",
+          numberAsString);
+      return 0;
+    }
+  }
 }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/util/SchemaUtils.java b/opendj-server-legacy/src/main/java/org/opends/server/util/SchemaUtils.java
index 30a9581..25ffcde 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/util/SchemaUtils.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/util/SchemaUtils.java
@@ -12,6 +12,7 @@
  * information: "Portions Copyright [year] [name of copyright owner]".
  *
  * Copyright 2016 ForgeRock AS.
+ * Portions Copyright 2026 3A Systems, LLC.
  */
 package org.opends.server.util;
 
@@ -413,7 +414,16 @@
   public static int parseRuleID(String definition) throws DirectoryException
   {
     // Reuse code of parseOID, even though this is not an OID
-    return Integer.parseInt(parseOID(definition, ERR_PARSING_DIT_STRUCTURE_RULE_RULEID));
+    final String ruleID = parseOID(definition, ERR_PARSING_DIT_STRUCTURE_RULE_RULEID);
+    try
+    {
+      return Integer.parseInt(ruleID);
+    }
+    catch (NumberFormatException e)
+    {
+      throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX,
+          ERR_PARSING_DIT_STRUCTURE_RULE_RULEID.get(definition), e);
+    }
   }
 
   /**
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/replication/common/CSNTest.java b/opendj-server-legacy/src/test/java/org/opends/server/replication/common/CSNTest.java
index 1c65a05..d92e96d 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/replication/common/CSNTest.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/replication/common/CSNTest.java
@@ -22,6 +22,7 @@
 import java.util.Iterator;
 import java.util.List;
 
+import org.forgerock.i18n.LocalizedIllegalArgumentException;
 import org.opends.server.replication.ReplicationTestCase;
 import org.opends.server.util.TimeThread;
 import org.testng.annotations.DataProvider;
@@ -74,6 +75,28 @@
        "The encoding/decoding of CSN is not reversible for toString()");
  }
 
+  /** Create invalid CSN string representations. */
+  @DataProvider(name = "invalidCSNStrings")
+  public Object[][] createInvalidCSNStrings()
+  {
+    return new Object[][] {
+      { null },
+      { "" },
+      { "\u0001" }, // truncated CSN read from a legacy replication message
+      { "0000000000012abc002d0000007" }, // one character too short
+      { "000000000001zabc002d0000007b" }, // non hexadecimal timestamp
+      { "0000000000012abc002d0000007z" }, // non hexadecimal seqnum
+    };
+  }
+
+  /** Test constructor from an invalid String. */
+  @Test(dataProvider = "invalidCSNStrings",
+      expectedExceptions = LocalizedIllegalArgumentException.class)
+  public void csnDecodeInvalidString(String str) throws Exception
+  {
+    new CSN(str);
+  }
+
   /** Create CSN. */
   @DataProvider(name = "createCSN")
   public Object[][] createCSNData()
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/replication/protocol/ByteArrayTest.java b/opendj-server-legacy/src/test/java/org/opends/server/replication/protocol/ByteArrayTest.java
index a10c53f..05cb4f2 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/replication/protocol/ByteArrayTest.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/replication/protocol/ByteArrayTest.java
@@ -12,6 +12,7 @@
  * information: "Portions Copyright [year] [name of copyright owner]".
  *
  * Copyright 2014-2016 ForgeRock AS.
+ * Portions Copyright 2026 3A Systems, LLC.
  */
 package org.opends.server.replication.protocol;
 
@@ -209,6 +210,13 @@
   }
 
   @Test(expectedExceptions = DataFormatException.class)
+  public void testByteArrayScanner_nextCSNUTF8_throwsExceptionWhenNonHexCSN() throws Exception
+  {
+    final byte[] bytes = new ByteArrayBuilder().appendString("000000000001zabc002d0000007b").toByteArray();
+    new ByteArrayScanner(bytes).nextCSNUTF8();
+  }
+
+  @Test(expectedExceptions = DataFormatException.class)
   public void testByteArrayScanner_nextDN_throwsExceptionWhenInvalidDN() throws Exception
   {
     final byte[] bytes = new ByteArrayBuilder().appendString("this is not a valid DN").toByteArray();

--
Gitblit v1.10.0