Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,11 @@ public byte peek(int offset) {
* of the underlying byte sequence.
*/
public void skip(final int length) {
position(pos + length);
final long newPos = (long) pos + length;
if (newPos < 0 || newPos > sequence.length()) {
throw new IndexOutOfBoundsException();
}
position((int) newPos);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
* information: "Portions Copyright [year] [name of copyright owner]".
*
* Copyright 2012-2016 ForgeRock AS.
* Portions Copyright 2026 3A Systems, LLC.
*/
package org.forgerock.opendj.ldap;

Expand Down Expand Up @@ -653,15 +654,35 @@ private static GeneralizedTime finishDecodingFraction(final String value, final
throw new LocalizedIllegalArgumentException(message);
}

final Double fractionValue = Double.parseDouble(fractionBuffer.toString());
final int additionalMilliseconds = (int) Math.round(fractionValue * multiplier);
final double fractionValue;
try {
fractionValue = Double.parseDouble(fractionBuffer.toString());
} catch (final NumberFormatException e) {
final LocalizableMessage message =
WARN_ATTR_SYNTAX_GENERALIZED_TIME_ILLEGAL_TIME.get(value, fractionBuffer);
throw new LocalizedIllegalArgumentException(message, e);
}
if (fractionValue < 0.0d || fractionValue >= 1.0d) {
// "0." followed by 17 nines parses as exactly 1.0, so reject before scaling.
final LocalizableMessage message =
WARN_ATTR_SYNTAX_GENERALIZED_TIME_ILLEGAL_TIME.get(value, fractionBuffer);
throw new LocalizedIllegalArgumentException(message);
}
final long additionalMilliseconds = Math.round(fractionValue * multiplier);
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
if (additionalMilliseconds >= multiplier) {
// 16 nines: 0.9999999999999999 * 1000 still rounds up to 1000. The calendar below
// only validates lazily, so reject the out-of-range value here.
final LocalizableMessage message =
WARN_ATTR_SYNTAX_GENERALIZED_TIME_ILLEGAL_TIME.get(value, fractionBuffer);
throw new LocalizedIllegalArgumentException(message);
}

try {
final GregorianCalendar calendar = new GregorianCalendar();
calendar.setLenient(false);
calendar.setTimeZone(timeZone);
calendar.set(year, month, day, hour, minute, second);
calendar.set(Calendar.MILLISECOND, additionalMilliseconds);
calendar.set(Calendar.MILLISECOND, (int) additionalMilliseconds);
return new GeneralizedTime(calendar, null, Long.MIN_VALUE, value);
} catch (final Exception e) {
// This should only happen if the provided date wasn't legal
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
*
* Copyright 2009 Sun Microsystems, Inc.
* Portions Copyright 2014-2015 ForgeRock AS.
* Portions Copyright 2026 3A Systems, LLC.
*/
package org.forgerock.opendj.ldap;

Expand Down Expand Up @@ -347,6 +348,14 @@ public void testSkip(ByteSequenceReader reader, byte[] ba) {
reader.skip(1);
}

@Test(dataProvider = "readerProvider", expectedExceptions = IndexOutOfBoundsException.class)
public void testSkipOverflow(ByteSequenceReader reader, byte[] ba) {
reader.rewind();
reader.skip(ba.length);
// pos + Integer.MAX_VALUE overflows int; must throw, not wrap around.
reader.skip(Integer.MAX_VALUE);
}

@Test(dataProvider = "readerProvider")
public void testPeek(ByteSequenceReader reader, byte[] ba) {
reader.rewind();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
*
* Copyright 2009 Sun Microsystems, Inc.
* Portions copyright 2012-2015 ForgeRock AS.
* Portions Copyright 2026 3A Systems, LLC.
*/
package org.forgerock.opendj.ldap;

Expand Down Expand Up @@ -67,7 +68,11 @@ public Object[][] invalidStrings() {
{ "2006122a235959Z" }, { "20060031235959Z" }, { "20061331235959Z" },
{ "20062231235959Z" }, { "20061232235959Z" }, { "2006123123595aZ" },
{ "200a1231235959Z" }, { "2006j231235959Z" }, { "200612-1235959Z" },
{ "20061231#35959Z" }, { "2006" }, };
{ "20061231#35959Z" }, { "2006" },
// Double.parseDouble rounds 17 nines up to exactly 1.0.
{ "20240101000000.99999999999999999Z" },
// 16 nines stay below 1.0 but scale and round to 1000 milliseconds.
{ "20240101000000.9999999999999999Z" }, };
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
*
* Copyright 2006-2009 Sun Microsystems, Inc.
* Portions Copyright 2013-2015 ForgeRock AS.
* Portions Copyright 2026 3A Systems, LLC.
*/
package org.opends.server.replication.common;

Expand Down Expand Up @@ -319,11 +320,11 @@ else if (csn1.timeStamp != csn2.timeStamp)
}
else if (csn1.seqnum != csn2.seqnum)
{
return csn1.seqnum - csn2.seqnum;
return Integer.compare(csn1.seqnum, csn2.seqnum);
}
else
{
return csn1.serverId - csn2.serverId;
return Integer.compare(csn1.serverId, csn2.serverId);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
*
* Copyright 2006-2009 Sun Microsystems, Inc.
* Portions Copyright 2013-2016 ForgeRock AS.
* Portions Copyright 2026 3A Systems, LLC.
*/
package org.opends.server.replication.common;

Expand Down Expand Up @@ -77,9 +78,9 @@ public void csnEncodeDecode(long time, int seq, int id, String str) throws Excep
@DataProvider(name = "createCSN")
public Object[][] createCSNData()
{
long time[] = {1, TimeThread.getTime()};
int seq[] = {0, 123};
int id [] = {1, 45};
long time[] = {1, TimeThread.getTime(), 1, 1};
int seq[] = {0, 123, Integer.MIN_VALUE, Integer.MAX_VALUE - 1};
int id [] = {1, 45, 1, 1};

Object[][] obj = new Object[time.length][5];
for (int i=0; i<time.length; i++)
Expand Down Expand Up @@ -140,6 +141,26 @@ public void csnCompare(CSN csn1, CSN csn2, CSN csn3, CSN csn4, CSN csn5) throws
assertTrue(CSN.compare(csn5, csn1) > 0);
}

/**
* Test that {@link CSN#compare(CSN, CSN)} orders extreme seqnums correctly and
* transitively: subtraction-based comparison overflowed for MIN_VALUE vs
* MAX_VALUE at equal timestamps and inverted the sign, which is fatal for
* TreeMaps keyed on CSN.
*/
@Test
public void csnCompareExtremeSeqnums() throws Exception
{
final CSN minSeqnum = new CSN(1, Integer.MIN_VALUE, 1);
final CSN zeroSeqnum = new CSN(1, 0, 1);
final CSN maxSeqnum = new CSN(1, Integer.MAX_VALUE, 1);

assertTrue(CSN.compare(minSeqnum, zeroSeqnum) < 0);
assertTrue(CSN.compare(zeroSeqnum, maxSeqnum) < 0);
assertTrue(CSN.compare(minSeqnum, maxSeqnum) < 0);
assertTrue(CSN.compare(maxSeqnum, minSeqnum) > 0);
assertEquals(CSN.compare(maxSeqnum, maxSeqnum), 0);
}

/** Test {@link CSN#isOlderThan(CSN)} method. */
@Test(dataProvider = "createCSN")
public void csnOlder(CSN csn1, CSN csn2, CSN csn3, CSN csn4, CSN csn5) throws Exception
Expand Down
Loading