You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2026/09/09 02:52:13 UTC
(directory-ldap-api) branch master updated: Fix the GeneralizedTime parsing to avoid accepting garbage at the end of a time
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/directory-ldap-api.git
The following commit(s) were added to refs/heads/master by this push:
new 85f9835b0 Fix the GeneralizedTime parsing to avoid accepting garbage at the end of a time
85f9835b0 is described below
commit 85f9835b0d18e2c9f00b9c60353dd0b5db0ac734
Author: emmanuel lecharny <el...@apache.org>
AuthorDate: Wed Sep 9 04:52:09 2026 +0200
Fix the GeneralizedTime parsing to avoid accepting garbage at the end of
a time
---
.../apache/directory/api/util/GeneralizedTime.java | 8 +-
.../util/GeneralizedTimeStrictTimezoneTest.java | 88 ++++++++++++++++++++++
2 files changed, 95 insertions(+), 1 deletion(-)
diff --git a/util/src/main/java/org/apache/directory/api/util/GeneralizedTime.java b/util/src/main/java/org/apache/directory/api/util/GeneralizedTime.java
index c81dbdee6..8f50ca6bc 100644
--- a/util/src/main/java/org/apache/directory/api/util/GeneralizedTime.java
+++ b/util/src/main/java/org/apache/directory/api/util/GeneralizedTime.java
@@ -448,7 +448,13 @@ public class GeneralizedTime implements Comparable<GeneralizedTime>
throw new ParseException( I18n.err( I18n.ERR_17053_MISSING_TZ ), pos + 1 + digits.length() );
}
}
- }
+ else
+ {
+ // The time zone must be 'Z', '+HH[MM]' or '-HH[MM]' and must terminate the
+ // string: anything else (e.g. trailing garbage after a fraction) is invalid
+ throw new ParseException( I18n.err( I18n.ERR_17053_MISSING_TZ ), pos );
+ }
+ }
/**
diff --git a/util/src/test/java/org/apache/directory/api/util/GeneralizedTimeStrictTimezoneTest.java b/util/src/test/java/org/apache/directory/api/util/GeneralizedTimeStrictTimezoneTest.java
new file mode 100644
index 000000000..b1eb28aa4
--- /dev/null
+++ b/util/src/test/java/org/apache/directory/api/util/GeneralizedTimeStrictTimezoneTest.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.directory.api.util;
+
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.text.ParseException;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.parallel.Execution;
+import org.junit.jupiter.api.parallel.ExecutionMode;
+
+
+/**
+ * Tests that GeneralizedTime rejects any time zone token other than 'Z',
+ * '+HH[MM]' or '-HH[MM]'. Before this was enforced, a value containing a
+ * fraction could carry unlimited trailing garbage ("20250101120000.5whatever")
+ * and still parse successfully as GMT, creating a parsing differential with
+ * strict RFC 4517 implementations.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+@Execution( ExecutionMode.CONCURRENT )
+public class GeneralizedTimeStrictTimezoneTest
+{
+ /**
+ * Trailing garbage after a fraction of a second must be rejected.
+ */
+ @Test
+ public void testFractionOfSecondTrailingGarbageRejected()
+ {
+ assertThrows( ParseException.class, () -> new GeneralizedTime( "20250101120000.5X" ) );
+ assertThrows( ParseException.class, () -> new GeneralizedTime( "20991231235959.9UNTIL-FOREVER" ) );
+ }
+
+
+ /**
+ * Trailing garbage after a fraction of a minute must be rejected.
+ */
+ @Test
+ public void testFractionOfMinuteTrailingGarbageRejected()
+ {
+ assertThrows( ParseException.class, () -> new GeneralizedTime( "202501011200.5garbage" ) );
+ }
+
+
+ /**
+ * Trailing garbage after a fraction of an hour must be rejected.
+ */
+ @Test
+ public void testFractionOfHourTrailingGarbageRejected()
+ {
+ assertThrows( ParseException.class, () -> new GeneralizedTime( "2025010112.5garbage" ) );
+ }
+
+
+ /**
+ * Valid time zone tokens after a fraction must still be accepted.
+ */
+ @Test
+ public void testValidTimezoneAfterFractionStillAccepted() throws ParseException
+ {
+ assertNotNull( new GeneralizedTime( "20250101120000.5Z" ) );
+ assertNotNull( new GeneralizedTime( "20250101120000.5+0100" ) );
+ assertNotNull( new GeneralizedTime( "20250101120000.5-05" ) );
+ assertNotNull( new GeneralizedTime( "202501011200.5Z" ) );
+ assertNotNull( new GeneralizedTime( "2025010112.5Z" ) );
+ }
+}