mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Valery Kharseko
13 hours ago e24c2780b6d44c7e5d386e70a1fb3346149ccdc9
Fix CodeQL note-severity alerts: array logging and uncaught NumberFormatException (#817)
23 files modified
345 ■■■■ changed files
opendj-core/src/main/java/org/forgerock/opendj/ldap/GSERParser.java 9 ●●●● patch | view | raw | blame | history
opendj-core/src/main/java/org/forgerock/opendj/ldap/MemoryBackend.java 29 ●●●●● patch | view | raw | blame | history
opendj-core/src/test/java/org/forgerock/opendj/ldap/GSERParserTestCase.java 5 ●●●● patch | view | raw | blame | history
opendj-core/src/test/java/org/forgerock/opendj/ldap/MemoryBackendTestCase.java 17 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/guitools/controlpanel/browser/BrowserController.java 3 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/backends/ChangelogBackend.java 16 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/backends/jdbc/CachedConnection.java 31 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/ID2ChildrenCount.java 3 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/ID2Entry.java 26 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/ImportLDIFReader.java 3 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/core/PasswordPolicyState.java 4 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/protocols/asn1/GSERParser.java 12 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/replication/common/CSN.java 27 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/replication/protocol/ByteArrayScanner.java 23 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/replication/server/changelog/file/FileReplicaDB.java 10 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/replication/server/changelog/file/ReplicationEnvironment.java 19 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/schema/GeneralizedTimeSyntax.java 4 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/types/HostPort.java 7 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/types/SubtreeSpecification.java 8 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/util/BackupManager.java 46 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/util/SchemaUtils.java 12 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/test/java/org/opends/server/replication/common/CSNTest.java 23 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/test/java/org/opends/server/replication/protocol/ByteArrayTest.java 8 ●●●●● patch | view | raw | blame | history
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);
        }
    }
    /**
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 {
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}
        };
    }
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());
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();
    }
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
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;
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();
  }
  /**
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));
    }
  }
}
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;
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;
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);
    }
  }
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));
    }
  }
  /**
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());
    }
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,8 +417,16 @@
    @Override
    public CSN decodeKeyFromString(String key) throws ChangelogException
    {
      try
      {
      return new CSN(key);
    }
      catch (LocalizedIllegalArgumentException e)
      {
        throw new ChangelogException(
            ERR_CHANGELOG_UNABLE_TO_DECODE_KEY_FROM_STRING.get(key), e);
      }
    }
    @Override
    public String encodeKeyToString(CSN key)
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;
opendj-server-legacy/src/main/java/org/opends/server/schema/GeneralizedTimeSyntax.java
@@ -1200,11 +1200,11 @@
              ResultCode.INVALID_ATTRIBUTE_SYNTAX, message);
    }
    try
    {
    double fractionValue = Double.parseDouble(fractionBuffer.toString());
    long additionalMilliseconds = Math.round(fractionValue * multiplier);
    try
    {
      GregorianCalendar calendar = new GregorianCalendar();
      calendar.setLenient(false);
      calendar.setTimeZone(timeZone);
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;
opendj-server-legacy/src/main/java/org/opends/server/types/SubtreeSpecification.java
@@ -568,8 +568,16 @@
        NoSuchElementException
    {
      final String s = nextValue(INT, INT_TOKEN);
      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();
      }
    }
    /**
     * Scans the next token of the input as a key value.
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;
    }
  }
}
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);
    }
  }
  /**
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()
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();