From d7962c808b9ada721faaf1cedf8899e167d446ee Mon Sep 17 00:00:00 2001 From: Sahana Bogar Date: Thu, 30 Jul 2026 12:44:39 +0530 Subject: [PATCH 1/2] count unpaired carriage returns in adjustForLineEnding --- .../commons/validator/GenericValidator.java | 5 +++- .../validator/GenericValidatorTest.java | 29 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/apache/commons/validator/GenericValidator.java b/src/main/java/org/apache/commons/validator/GenericValidator.java index d212aa06e..fcf49a58e 100644 --- a/src/main/java/org/apache/commons/validator/GenericValidator.java +++ b/src/main/java/org/apache/commons/validator/GenericValidator.java @@ -53,7 +53,10 @@ private static int adjustForLineEnding(final String value, final int lineEndLeng } } final int rnCount = rCount + nCount; - return nCount * lineEndLength - rnCount; + // A carriage return that is not paired with a line feed is still a line ending, so the number of line + // endings is at least the number of carriage returns as well as the number of line feeds. Counting only + // the line feeds discounts every character of a CR-only value, leaving its adjusted length at zero. + return Math.max(nCount, rCount) * lineEndLength - rnCount; } /** diff --git a/src/test/java/org/apache/commons/validator/GenericValidatorTest.java b/src/test/java/org/apache/commons/validator/GenericValidatorTest.java index 88a873104..4463a4f6c 100644 --- a/src/test/java/org/apache/commons/validator/GenericValidatorTest.java +++ b/src/test/java/org/apache/commons/validator/GenericValidatorTest.java @@ -34,6 +34,35 @@ void testIsDate() { assertFalse(GenericValidator.isDate("2/12/1999", "MM/dd/yyyy", true), "abbreviated month"); } + /** + * A carriage return with no line feed next to it is a line ending in its own right, so it must not be + * discounted to zero characters. + */ + @Test + void testLengthUnpairedCarriageReturn() { + + // Use 0 for line end length + assertTrue(GenericValidator.maxLength("12345\r", 5, 0), "Max=5 End=0"); + + // Use 1 for line end length + assertFalse(GenericValidator.maxLength("12345\r", 5, 1), "Max=5 End=1"); + assertTrue(GenericValidator.maxLength("12345\r", 6, 1), "Max=6 End=1"); + + // Use 2 for line end length + assertFalse(GenericValidator.maxLength("12345\r", 6, 2), "Max=6 End=2"); + assertTrue(GenericValidator.maxLength("12345\r", 7, 2), "Max=7 End=2"); + + assertTrue(GenericValidator.minLength("12345\r", 7, 2), "Min=7 End=2"); + assertFalse(GenericValidator.minLength("12345\r", 8, 2), "Min=8 End=2"); + + // Carriage returns alone used to leave the adjusted length at zero whatever the value's length + assertFalse(GenericValidator.maxLength("\r\r\r\r\r", 1, 2), "Max=1 End=2"); + + // The paired form is unchanged + assertFalse(GenericValidator.maxLength("12345\r\n", 6, 2), "Max=6 End=2 paired"); + assertTrue(GenericValidator.maxLength("12345\r\n", 7, 2), "Max=7 End=2 paired"); + } + @Test void testMaxLength() { From 2f09ba7d371c246d2f45ddbaefaeb58ba467fde5 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 31 Jul 2026 17:54:10 -0400 Subject: [PATCH 2/2] Refactor testLengthUnpairedCarriageReturn method --- .../org/apache/commons/validator/GenericValidatorTest.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/test/java/org/apache/commons/validator/GenericValidatorTest.java b/src/test/java/org/apache/commons/validator/GenericValidatorTest.java index 4463a4f6c..e796f8f8f 100644 --- a/src/test/java/org/apache/commons/validator/GenericValidatorTest.java +++ b/src/test/java/org/apache/commons/validator/GenericValidatorTest.java @@ -40,24 +40,18 @@ void testIsDate() { */ @Test void testLengthUnpairedCarriageReturn() { - // Use 0 for line end length assertTrue(GenericValidator.maxLength("12345\r", 5, 0), "Max=5 End=0"); - // Use 1 for line end length assertFalse(GenericValidator.maxLength("12345\r", 5, 1), "Max=5 End=1"); assertTrue(GenericValidator.maxLength("12345\r", 6, 1), "Max=6 End=1"); - // Use 2 for line end length assertFalse(GenericValidator.maxLength("12345\r", 6, 2), "Max=6 End=2"); assertTrue(GenericValidator.maxLength("12345\r", 7, 2), "Max=7 End=2"); - assertTrue(GenericValidator.minLength("12345\r", 7, 2), "Min=7 End=2"); assertFalse(GenericValidator.minLength("12345\r", 8, 2), "Min=8 End=2"); - // Carriage returns alone used to leave the adjusted length at zero whatever the value's length assertFalse(GenericValidator.maxLength("\r\r\r\r\r", 1, 2), "Max=1 End=2"); - // The paired form is unchanged assertFalse(GenericValidator.maxLength("12345\r\n", 6, 2), "Max=6 End=2 paired"); assertTrue(GenericValidator.maxLength("12345\r\n", 7, 2), "Max=7 End=2 paired");