fix CVE-2020-10693

This commit is contained in:
wangxiao65 2021-03-16 09:27:59 +08:00
parent e85c0e88c7
commit 3c1f5da406
6 changed files with 1204 additions and 1 deletions

70
CVE-2020-10693-1.patch Normal file
View File

@ -0,0 +1,70 @@
From 29bd0f42bf63e28d9a71adef02af67b319144576 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= <yoann@hibernate.org>
Date: Mon, 24 Feb 2020 17:58:41 +0100
Subject: [PATCH] HV-1774 Do not interpret '$\A{1+1}' in message templates
---
.../messageinterpolation/parser/ELState.java | 6 +++++-
.../TokenCollectorTest.java | 21 ++++++++++++++++++-
2 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/ELState.java b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/ELState.java
index 9460fae05..fda95a153 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/ELState.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/ELState.java
@@ -51,7 +51,11 @@ public void handleEndTerm(char character, TokenCollector tokenCollector) throws
@Override
public void handleEscapeCharacter(char character, TokenCollector tokenCollector)
throws MessageDescriptorFormatException {
- tokenCollector.transitionState( new EscapedState( this ) );
+ tokenCollector.appendToToken( TokenCollector.EL_DESIGNATOR );
+ tokenCollector.appendToToken( character );
+ // Do not go back to this state after the escape: $\ is not the start of an EL expression
+ ParserState stateAfterEscape = new MessageState();
+ tokenCollector.transitionState( new EscapedState( stateAfterEscape ) );
}
@Override
diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenCollectorTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenCollectorTest.java
index 972a9e051..ab9299f17 100644
--- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenCollectorTest.java
+++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenCollectorTest.java
@@ -8,7 +8,11 @@
import org.hibernate.validator.internal.engine.messageinterpolation.InterpolationTermType;
import org.hibernate.validator.internal.engine.messageinterpolation.parser.MessageDescriptorFormatException;
+import org.hibernate.validator.internal.engine.messageinterpolation.parser.Token;
import org.hibernate.validator.internal.engine.messageinterpolation.parser.TokenCollector;
+
+import org.assertj.core.api.Assertions;
+import org.assertj.core.api.ListAssert;
import org.testng.annotations.Test;
/**
@@ -29,10 +33,25 @@ public void testParameterWithoutOpeningBraceThrowsException() throws Exception {
}
@Test(expectedExceptions = MessageDescriptorFormatException.class, expectedExceptionsMessageRegExp = "HV000168.*")
- public void testELExpressionWithoutOpeningBraceThrowsException() throws Exception {
+ public void testELExpressionDollarThenClosingBraceThrowsException() throws Exception {
new TokenCollector( "$}", InterpolationTermType.EL );
}
+ @Test
+ public void testELExpressionDollarThenEscapeInterpretedAsLiterals() {
+ ListAssert<Token> assertion = Assertions.assertThat(
+ new TokenCollector( "$\\A{1+1}", InterpolationTermType.EL )
+ .getTokenList()
+ )
+ .hasSize( 2 );
+ assertion.element( 0 )
+ .returns( "$\\A", Token::getTokenValue )
+ .returns( false, Token::isParameter );
+ assertion.element( 1 )
+ .returns( "{1+1}", Token::getTokenValue )
+ .returns( false, Token::isParameter );
+ }
+
@Test(expectedExceptions = MessageDescriptorFormatException.class, expectedExceptionsMessageRegExp = "HV000168.*")
public void testTermWithoutClosingBraceThrowsException() throws Exception {
new TokenCollector( "{foo", InterpolationTermType.PARAMETER );

79
CVE-2020-10693-2.patch Normal file
View File

@ -0,0 +1,79 @@
From 4b9f2a1a3e1c67fbd29a7fc710c611d7aca6eab9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= <yoann@hibernate.org>
Date: Tue, 25 Feb 2020 13:05:53 +0100
Subject: [PATCH] HV-1774 Fix an invalid error message for unbalanced '{'/'}'
---
.../internal/engine/messageinterpolation/parser/ELState.java | 2 +-
.../messageinterpolation/parser/InterpolationTermState.java | 2 +-
.../engine/messageinterpolation/parser/MessageState.java | 2 +-
.../org/hibernate/validator/internal/util/logging/Log.java | 4 ++--
4 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/ELState.java b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/ELState.java
index fda95a153..9f480f848 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/ELState.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/ELState.java
@@ -42,7 +42,7 @@ public void handleBeginTerm(char character, TokenCollector tokenCollector) throw
@Override
public void handleEndTerm(char character, TokenCollector tokenCollector) throws MessageDescriptorFormatException {
- throw log.getNonTerminatedParameterException(
+ throw log.getUnbalancedBeginEndParameterException(
tokenCollector.getOriginalMessageDescriptor(),
character
);
diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/InterpolationTermState.java b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/InterpolationTermState.java
index 9b00c3594..809db34dd 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/InterpolationTermState.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/InterpolationTermState.java
@@ -17,7 +17,7 @@
@Override
public void terminate(TokenCollector tokenCollector) throws MessageDescriptorFormatException {
- throw log.getNonTerminatedParameterException(
+ throw log.getUnbalancedBeginEndParameterException(
tokenCollector.getOriginalMessageDescriptor(),
TokenCollector.BEGIN_TERM
);
diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/MessageState.java b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/MessageState.java
index a8b1de63f..88171668a 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/MessageState.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/MessageState.java
@@ -40,7 +40,7 @@ public void handleBeginTerm(char character, TokenCollector tokenCollector) throw
@Override
public void handleEndTerm(char character, TokenCollector tokenCollector) throws MessageDescriptorFormatException {
- throw log.getNonTerminatedParameterException(
+ throw log.getUnbalancedBeginEndParameterException(
tokenCollector.getOriginalMessageDescriptor(),
character
);
diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/BeginState.java b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/BeginState.java
index 678f16e..7d544de 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/BeginState.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/BeginState.java
@@ -48,7 +48,7 @@ public void handleBeginTerm(char character, TokenCollector tokenCollector) throw
@Override
public void handleEndTerm(char character, TokenCollector tokenCollector) throws MessageDescriptorFormatException {
- throw log.getNonTerminatedParameterException( tokenCollector.getOriginalMessageDescriptor(), character );
+ throw log.getUnbalancedBeginEndParameterException( tokenCollector.getOriginalMessageDescriptor(), character );
}
@Override
diff --git a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java
index 3effce1c9..33034cb0c 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/util/logging/Log.java
@@ -552,8 +552,8 @@ ConstraintDefinitionException getValidatorForCrossParameterConstraintMustEitherV
ValidationException getOverridingConstraintDefinitionsInMultipleMappingFilesException(String constraintClass);
@Message(id = 168,
- value = "The message descriptor '%1$s' contains an unbalanced meta character '%2$c' parameter.")
- MessageDescriptorFormatException getNonTerminatedParameterException(String messageDescriptor, char character);
+ value = "The message descriptor '%1$s' contains an unbalanced meta character '%2$c'.")
+ MessageDescriptorFormatException getUnbalancedBeginEndParameterException(String messageDescriptor, char character);
@Message(id = 169,
value = "The message descriptor '%1$s' has nested parameters.")

516
CVE-2020-10693-3.patch Normal file
View File

@ -0,0 +1,516 @@
From c7c904db1b146d24e25927b613155d130bbe40d1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= <yoann@hibernate.org>
Date: Tue, 25 Feb 2020 15:17:03 +0100
Subject: [PATCH] HV-1774 Add a few tests to demonstrate the behavior of
TokenCollector
---
.../AbstractTokenCollectorTest.java | 186 ++++++++++++++++++
.../TokenCollectorMessageExpressionTest.java | 110 +++++++++++
.../TokenCollectorMessageParameterTest.java | 115 +++++++++++
.../TokenCollectorTest.java | 64 ------
4 files changed, 411 insertions(+), 64 deletions(-)
create mode 100644 engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/AbstractTokenCollectorTest.java
create mode 100644 engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenCollectorMessageExpressionTest.java
create mode 100644 engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenCollectorMessageParameterTest.java
delete mode 100644 engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenCollectorTest.java
diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/AbstractTokenCollectorTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/AbstractTokenCollectorTest.java
new file mode 100644
index 000000000..004d5c9bd
--- /dev/null
+++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/AbstractTokenCollectorTest.java
@@ -0,0 +1,186 @@
+/*
+ * Hibernate Validator, declare and validate application constraints
+ *
+ * License: Apache License, Version 2.0
+ * See the license.txt file in the root directory or <http://www.apache.org/licenses/LICENSE-2.0>.
+ */
+package org.hibernate.validator.test.internal.engine.messageinterpolation;
+
+import org.hibernate.validator.internal.engine.messageinterpolation.InterpolationTermType;
+import org.hibernate.validator.internal.engine.messageinterpolation.parser.MessageDescriptorFormatException;
+import org.hibernate.validator.internal.engine.messageinterpolation.parser.Token;
+import org.hibernate.validator.internal.engine.messageinterpolation.parser.TokenCollector;
+
+import org.assertj.core.api.Assertions;
+import org.testng.annotations.Test;
+
+/**
+ * Abstract base for {@code TokenCollector} tests.
+ *
+ * @author Hardy Ferentschik
+ */
+public abstract class AbstractTokenCollectorTest {
+
+ protected abstract InterpolationTermType getInterpolationTermType();
+
+ @Test
+ public void testLiteral() {
+ Assertions.assertThat(
+ new TokenCollector( "foo bar", getInterpolationTermType() )
+ .getTokenList()
+ )
+ .hasSize( 1 )
+ .element( 0 )
+ .returns( "foo bar", Token::getTokenValue )
+ .returns( false, Token::isParameter );
+ }
+
+ @Test(expectedExceptions = MessageDescriptorFormatException.class, expectedExceptionsMessageRegExp = "HV000169.*")
+ public void testNestedParametersThrowException() {
+ new TokenCollector( "#{foo {}", getInterpolationTermType() );
+ }
+
+ @Test(expectedExceptions = MessageDescriptorFormatException.class, expectedExceptionsMessageRegExp = "HV000168.*")
+ public void testClosingBraceWithoutOpeningBraceThrowsException() {
+ new TokenCollector( "foo}", getInterpolationTermType() );
+ }
+
+ @Test(expectedExceptions = MessageDescriptorFormatException.class, expectedExceptionsMessageRegExp = "HV000168.*")
+ public void testOpeningBraceWithoutClosingBraceThrowsException() {
+ new TokenCollector( "{foo", getInterpolationTermType() );
+ }
+
+ @Test
+ public void testBackslashEscapesNonMetaCharacter() {
+ Assertions.assertThat(
+ new TokenCollector( "foo \\bar", getInterpolationTermType() )
+ .getTokenList()
+ )
+ .hasSize( 1 )
+ .element( 0 )
+ // Backslashes are removed later, in AbstractMessageInterpolator.replaceEscapedLiterals
+ .returns( "foo \\bar", Token::getTokenValue )
+ .returns( false, Token::isParameter );
+ }
+
+ @Test
+ public void testBackslashEscapesDollar() {
+ Assertions.assertThat(
+ new TokenCollector( "foo \\$ bar", getInterpolationTermType() )
+ .getTokenList()
+ )
+ .hasSize( 1 )
+ .element( 0 )
+ // Backslashes are removed later, in AbstractMessageInterpolator.replaceEscapedLiterals
+ .returns( "foo \\$ bar", Token::getTokenValue )
+ .returns( false, Token::isParameter );
+ }
+
+ @Test
+ public void testBackslashEscapesOpeningBrace() {
+ Assertions.assertThat(
+ new TokenCollector( "foo \\{ bar", getInterpolationTermType() )
+ .getTokenList()
+ )
+ .hasSize( 1 )
+ .element( 0 )
+ // Backslashes are removed later, in AbstractMessageInterpolator.replaceEscapedLiterals
+ .returns( "foo \\{ bar", Token::getTokenValue )
+ .returns( false, Token::isParameter );
+ }
+
+ @Test
+ public void testBackslashEscapesClosingBrace() {
+ Assertions.assertThat(
+ new TokenCollector( "foo \\} bar", getInterpolationTermType() )
+ .getTokenList()
+ )
+ .hasSize( 1 )
+ .element( 0 )
+ // Backslashes are removed later, in AbstractMessageInterpolator.replaceEscapedLiterals
+ .returns( "foo \\} bar", Token::getTokenValue )
+ .returns( false, Token::isParameter );
+ }
+
+ @Test
+ public void testBackslashEscapesBackslash() {
+ Assertions.assertThat(
+ new TokenCollector( "foo \\\\ bar", getInterpolationTermType() )
+ .getTokenList()
+ )
+ .hasSize( 1 )
+ .element( 0 )
+ // Backslashes are removed later, in AbstractMessageInterpolator.replaceEscapedLiterals
+ .returns( "foo \\\\ bar", Token::getTokenValue )
+ .returns( false, Token::isParameter );
+ }
+
+ @Test
+ public void testBackslashEscapesEL() {
+ Assertions.assertThat(
+ new TokenCollector( "foo \\$\\{bar\\}", getInterpolationTermType() )
+ .getTokenList()
+ )
+ .hasSize( 1 )
+ .element( 0 )
+ // Backslashes are removed later, in AbstractMessageInterpolator.replaceEscapedLiterals
+ .returns( "foo \\$\\{bar\\}", Token::getTokenValue )
+ // What's important is that we did NOT detect the expression
+ .returns( false, Token::isParameter );
+ }
+
+ @Test
+ public void testBackslashEscapesParameter() {
+ Assertions.assertThat(
+ new TokenCollector( "foo \\{bar\\}", getInterpolationTermType() )
+ .getTokenList()
+ )
+ .hasSize( 1 )
+ .element( 0 )
+ // Backslashes are removed later, in AbstractMessageInterpolator.replaceEscapedLiterals
+ .returns( "foo \\{bar\\}", Token::getTokenValue )
+ // What's important is that we did NOT detect the parameter
+ .returns( false, Token::isParameter );
+ }
+
+ @Test(expectedExceptions = MessageDescriptorFormatException.class, expectedExceptionsMessageRegExp = "HV000168.*")
+ public void testTrailingClosingBraceThrowsException() {
+ new TokenCollector( "this message contains a invalid parameter start token {", getInterpolationTermType() );
+ }
+
+ @Test
+ public void testDollarThenNonMetaCharacterInterpretedAsLiteral() {
+ Assertions.assertThat(
+ new TokenCollector( "$a", getInterpolationTermType() )
+ .getTokenList()
+ )
+ .hasSize( 1 )
+ .element( 0 )
+ .returns( "$a", Token::getTokenValue )
+ .returns( false, Token::isParameter );
+ }
+
+ @Test
+ public void testTrailingDollarInterpretedAsLiteral() {
+ Assertions.assertThat(
+ new TokenCollector( "foo $", getInterpolationTermType() )
+ .getTokenList()
+ )
+ .hasSize( 1 )
+ .element( 0 )
+ .returns( "foo $", Token::getTokenValue )
+ .returns( false, Token::isParameter );
+ }
+
+ @Test
+ public void testTrailingBackslashInterpretedAsLiteral() {
+ Assertions.assertThat(
+ new TokenCollector( "foo \\", getInterpolationTermType() )
+ .getTokenList()
+ )
+ .hasSize( 1 )
+ .element( 0 )
+ .returns( "foo \\", Token::getTokenValue )
+ .returns( false, Token::isParameter );
+ }
+}
diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenCollectorMessageExpressionTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenCollectorMessageExpressionTest.java
new file mode 100644
index 000000000..229e34174
--- /dev/null
+++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenCollectorMessageExpressionTest.java
@@ -0,0 +1,110 @@
+/*
+ * Hibernate Validator, declare and validate application constraints
+ *
+ * License: Apache License, Version 2.0
+ * See the license.txt file in the root directory or <http://www.apache.org/licenses/LICENSE-2.0>.
+ */
+package org.hibernate.validator.test.internal.engine.messageinterpolation;
+
+import org.hibernate.validator.internal.engine.messageinterpolation.InterpolationTermType;
+import org.hibernate.validator.internal.engine.messageinterpolation.parser.MessageDescriptorFormatException;
+import org.hibernate.validator.internal.engine.messageinterpolation.parser.Token;
+import org.hibernate.validator.internal.engine.messageinterpolation.parser.TokenCollector;
+
+import org.assertj.core.api.Assertions;
+import org.assertj.core.api.ListAssert;
+import org.testng.annotations.Test;
+
+/**
+ * Tests for {@code TokenCollector} in message expression mode.
+ *
+ * @author Hardy Ferentschik
+ */
+public class TokenCollectorMessageExpressionTest extends AbstractTokenCollectorTest {
+ @Override
+ protected InterpolationTermType getInterpolationTermType() {
+ return InterpolationTermType.EL;
+ }
+
+ // Several tests inherited from the abstract class
+
+ @Test
+ public void testMessageParameter() {
+ ListAssert<Token> assertion = Assertions.assertThat(
+ new TokenCollector( "foo {bar}", getInterpolationTermType() )
+ .getTokenList()
+ )
+ .hasSize( 2 );
+ assertion.element( 0 )
+ .returns( "foo ", Token::getTokenValue )
+ .returns( false, Token::isParameter );
+ assertion.element( 1 )
+ .returns( "{bar}", Token::getTokenValue )
+ .returns( false, Token::isParameter );
+ }
+
+ @Test
+ public void testMessageExpression() {
+ ListAssert<Token> assertion = Assertions.assertThat(
+ new TokenCollector( "foo ${bar}", getInterpolationTermType() )
+ .getTokenList()
+ )
+ .hasSize( 2 );
+ assertion.element( 0 )
+ .returns( "foo ", Token::getTokenValue )
+ .returns( false, Token::isParameter );
+ assertion.element( 1 )
+ .returns( "${bar}", Token::getTokenValue )
+ .returns( true, Token::isParameter );
+ }
+
+ @Test
+ public void testDollarThenDollarThenParameterInterpretedAsLiterals() {
+ ListAssert<Token> assertion = Assertions.assertThat(
+ new TokenCollector( "$${1+1}", getInterpolationTermType() )
+ .getTokenList()
+ )
+ .hasSize( 2 );
+ assertion.element( 0 )
+ .returns( "$$", Token::getTokenValue )
+ .returns( false, Token::isParameter );
+ assertion.element( 1 )
+ .returns( "{1+1}", Token::getTokenValue )
+ .returns( false, Token::isParameter );
+ }
+
+ @Test
+ public void testDollarThenDollarThenLiteralsInterpretedAsLiterals() {
+ ListAssert<Token> assertion = Assertions.assertThat(
+ new TokenCollector( "$$foo", getInterpolationTermType() )
+ .getTokenList()
+ )
+ .hasSize( 2 );
+ assertion.element( 0 )
+ .returns( "$$", Token::getTokenValue )
+ .returns( false, Token::isParameter );
+ assertion.element( 1 )
+ .returns( "foo", Token::getTokenValue )
+ .returns( false, Token::isParameter );
+ }
+
+ @Test(expectedExceptions = MessageDescriptorFormatException.class, expectedExceptionsMessageRegExp = "HV000168.*")
+ public void testDollarThenClosingBraceThrowsException() {
+ new TokenCollector( "$}", getInterpolationTermType() );
+ }
+
+ @Test
+ public void testDollarThenEscapeInterpretedAsLiterals() {
+ ListAssert<Token> assertion = Assertions.assertThat(
+ new TokenCollector( "$\\A{1+1}", getInterpolationTermType() )
+ .getTokenList()
+ )
+ .hasSize( 2 );
+ assertion.element( 0 )
+ .returns( "$\\A", Token::getTokenValue )
+ .returns( false, Token::isParameter );
+ assertion.element( 1 )
+ .returns( "{1+1}", Token::getTokenValue )
+ .returns( false, Token::isParameter );
+ }
+}
diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenCollectorMessageParameterTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenCollectorMessageParameterTest.java
new file mode 100644
index 000000000..9189f496b
--- /dev/null
+++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenCollectorMessageParameterTest.java
@@ -0,0 +1,115 @@
+/*
+ * Hibernate Validator, declare and validate application constraints
+ *
+ * License: Apache License, Version 2.0
+ * See the license.txt file in the root directory or <http://www.apache.org/licenses/LICENSE-2.0>.
+ */
+package org.hibernate.validator.test.internal.engine.messageinterpolation;
+
+import org.hibernate.validator.internal.engine.messageinterpolation.InterpolationTermType;
+import org.hibernate.validator.internal.engine.messageinterpolation.parser.MessageDescriptorFormatException;
+import org.hibernate.validator.internal.engine.messageinterpolation.parser.Token;
+import org.hibernate.validator.internal.engine.messageinterpolation.parser.TokenCollector;
+
+import org.assertj.core.api.Assertions;
+import org.assertj.core.api.ListAssert;
+import org.testng.annotations.Test;
+
+/**
+ * Tests for {@code TokenCollector} in message parameter mode.
+ *
+ * @author Hardy Ferentschik
+ */
+public class TokenCollectorMessageParameterTest extends AbstractTokenCollectorTest {
+ @Override
+ protected InterpolationTermType getInterpolationTermType() {
+ return InterpolationTermType.PARAMETER;
+ }
+
+ // Several tests inherited from the abstract class
+
+ @Test
+ public void testMessageParameter() {
+ ListAssert<Token> assertion = Assertions.assertThat(
+ new TokenCollector( "foo {bar}", getInterpolationTermType() )
+ .getTokenList()
+ )
+ .hasSize( 2 );
+ assertion.element( 0 )
+ .returns( "foo ", Token::getTokenValue )
+ .returns( false, Token::isParameter );
+ assertion.element( 1 )
+ .returns( "{bar}", Token::getTokenValue )
+ .returns( true, Token::isParameter );
+ }
+
+ @Test
+ public void testMessageExpression() {
+ ListAssert<Token> assertion = Assertions.assertThat(
+ new TokenCollector( "foo ${bar}", getInterpolationTermType() )
+ .getTokenList()
+ )
+ .hasSize( 2 );
+ /*
+ * 6.3.1.1:
+ * Parameter interpolation has precedence over message expressions.
+ * For example for the message descriptor ${value},
+ * trying to evaluate {value} as message parameter has precedence
+ * over evaluating ${value} as message expression.
+ */
+ assertion.element( 0 )
+ .returns( "foo $", Token::getTokenValue )
+ .returns( false, Token::isParameter );
+ assertion.element( 1 )
+ .returns( "{bar}", Token::getTokenValue )
+ .returns( true, Token::isParameter );
+ }
+
+ @Test
+ public void testDollarThenDollarThenParameterInterpretedAsLiteralAndParameter() {
+ ListAssert<Token> assertion = Assertions.assertThat(
+ new TokenCollector( "$${1+1}", getInterpolationTermType() )
+ .getTokenList()
+ )
+ .hasSize( 2 );
+ assertion.element( 0 )
+ .returns( "$$", Token::getTokenValue )
+ .returns( false, Token::isParameter );
+ assertion.element( 1 )
+ .returns( "{1+1}", Token::getTokenValue )
+ .returns( true, Token::isParameter );
+ }
+
+ @Test
+ public void testDollarThenDollarThenLiteralsInterpretedAsLiterals() {
+ ListAssert<Token> assertion = Assertions.assertThat(
+ new TokenCollector( "$$foo", getInterpolationTermType() )
+ .getTokenList()
+ )
+ .hasSize( 1 );
+ assertion.element( 0 )
+ .returns( "$$foo", Token::getTokenValue )
+ .returns( false, Token::isParameter );
+ }
+
+ @Test(expectedExceptions = MessageDescriptorFormatException.class, expectedExceptionsMessageRegExp = "HV000168.*")
+ public void testDollarThenClosingBraceThrowsException() {
+ // Fails because of the dangling closing brace; the dollar sign is irrelevant
+ new TokenCollector( "$}", getInterpolationTermType() );
+ }
+
+ @Test
+ public void testDollarThenEscapeInterpretedAsLiterals() {
+ ListAssert<Token> assertion = Assertions.assertThat(
+ new TokenCollector( "$\\A{1+1}", getInterpolationTermType() )
+ .getTokenList()
+ )
+ .hasSize( 2 );
+ assertion.element( 0 )
+ .returns( "$\\A", Token::getTokenValue )
+ .returns( false, Token::isParameter );
+ assertion.element( 1 )
+ .returns( "{1+1}", Token::getTokenValue )
+ .returns( true, Token::isParameter );
+ }
+}
diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenCollectorTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenCollectorTest.java
deleted file mode 100644
index ab9299f17..000000000
--- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenCollectorTest.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Hibernate Validator, declare and validate application constraints
- *
- * License: Apache License, Version 2.0
- * See the license.txt file in the root directory or <http://www.apache.org/licenses/LICENSE-2.0>.
- */
-package org.hibernate.validator.test.internal.engine.messageinterpolation;
-
-import org.hibernate.validator.internal.engine.messageinterpolation.InterpolationTermType;
-import org.hibernate.validator.internal.engine.messageinterpolation.parser.MessageDescriptorFormatException;
-import org.hibernate.validator.internal.engine.messageinterpolation.parser.Token;
-import org.hibernate.validator.internal.engine.messageinterpolation.parser.TokenCollector;
-
-import org.assertj.core.api.Assertions;
-import org.assertj.core.api.ListAssert;
-import org.testng.annotations.Test;
-
-/**
- * Tests for {@code TokenCollector}.
- *
- * @author Hardy Ferentschik
- */
-public class TokenCollectorTest {
-
- @Test(expectedExceptions = MessageDescriptorFormatException.class, expectedExceptionsMessageRegExp = "HV000169.*")
- public void testNestedParametersThrowException() throws Exception {
- new TokenCollector( "#{foo {}", InterpolationTermType.PARAMETER );
- }
-
- @Test(expectedExceptions = MessageDescriptorFormatException.class, expectedExceptionsMessageRegExp = "HV000168.*")
- public void testParameterWithoutOpeningBraceThrowsException() throws Exception {
- new TokenCollector( "foo}", InterpolationTermType.PARAMETER );
- }
-
- @Test(expectedExceptions = MessageDescriptorFormatException.class, expectedExceptionsMessageRegExp = "HV000168.*")
- public void testELExpressionDollarThenClosingBraceThrowsException() throws Exception {
- new TokenCollector( "$}", InterpolationTermType.EL );
- }
-
- @Test
- public void testELExpressionDollarThenEscapeInterpretedAsLiterals() {
- ListAssert<Token> assertion = Assertions.assertThat(
- new TokenCollector( "$\\A{1+1}", InterpolationTermType.EL )
- .getTokenList()
- )
- .hasSize( 2 );
- assertion.element( 0 )
- .returns( "$\\A", Token::getTokenValue )
- .returns( false, Token::isParameter );
- assertion.element( 1 )
- .returns( "{1+1}", Token::getTokenValue )
- .returns( false, Token::isParameter );
- }
-
- @Test(expectedExceptions = MessageDescriptorFormatException.class, expectedExceptionsMessageRegExp = "HV000168.*")
- public void testTermWithoutClosingBraceThrowsException() throws Exception {
- new TokenCollector( "{foo", InterpolationTermType.PARAMETER );
- }
-
- @Test(expectedExceptions = MessageDescriptorFormatException.class, expectedExceptionsMessageRegExp = "HV000168.*")
- public void testSingleClosingBraceThrowsException() throws Exception {
- new TokenCollector( "this message contains a invalid parameter start token {", InterpolationTermType.EL );
- }
-}

84
CVE-2020-10693-4.patch Normal file
View File

@ -0,0 +1,84 @@
From 93c027b954d4ccce1ad82b2f5e27e22357757fa8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= <yoann@hibernate.org>
Date: Mon, 24 Feb 2020 17:23:37 +0100
Subject: [PATCH] HV-1774 Test arbitrary code injection through
buildConstraintViolationWithTemplate()
---
.../ConstraintValidatorContextTest.java | 51 +++++++++++++++++++
1 file changed, 51 insertions(+)
diff --git a/engine/src/test/java/org/hibernate/validator/test/constraints/ConstraintValidatorContextTest.java b/engine/src/test/java/org/hibernate/validator/test/constraints/ConstraintValidatorContextTest.java
index 6094195e3..a89a97016 100644
--- a/engine/src/test/java/org/hibernate/validator/test/constraints/ConstraintValidatorContextTest.java
+++ b/engine/src/test/java/org/hibernate/validator/test/constraints/ConstraintValidatorContextTest.java
@@ -194,6 +194,20 @@ public void testAddParameterNodeForFieldLevelConstraintCausesException() throws
}
}
+ @Test
+ public void testInjectionCausedByRecklessConcatenation() {
+ String maliciousPayload = "$\\A{1 + 1}";
+
+ // Simulate user entry, through a web form for example
+ MyObjectWithELInjectionRiskCausedByRecklessConcatenation object = new MyObjectWithELInjectionRiskCausedByRecklessConcatenation();
+ object.field1 = maliciousPayload;
+ Set<ConstraintViolation<MyObjectWithELInjectionRiskCausedByRecklessConcatenation>> constraintViolations = validator.validate( object );
+ assertThat( constraintViolations ).containsOnlyViolations(
+ violationOf( ValidationWithELInjectionRiskCausedByRecklessConcatenation.class )
+ .withMessage( "Value '" + maliciousPayload + "' is invalid" )
+ );
+ }
+
@MyClassLevelValidation
private static class MyObject {
@NotNull
@@ -264,6 +278,13 @@ public String getName() {
}
}
+ @ValidationWithELInjectionRiskCausedByRecklessConcatenation
+ private static class MyObjectWithELInjectionRiskCausedByRecklessConcatenation {
+
+ String field1;
+
+ }
+
@Retention(RUNTIME)
@Constraint(validatedBy = MyClassLevelValidation.Validator.class)
public @interface MyClassLevelValidation {
@@ -496,4 +517,34 @@ public boolean isValid(String value, ConstraintValidatorContext context) {
}
}
+
+ @Retention(RUNTIME)
+ @Constraint(validatedBy = ValidationWithELInjectionRiskCausedByRecklessConcatenation.Validator.class)
+ public @interface ValidationWithELInjectionRiskCausedByRecklessConcatenation {
+ String message() default "failed";
+
+ Class<?>[] groups() default { };
+
+ Class<? extends Payload>[] payload() default { };
+
+ class Validator
+ implements ConstraintValidator<ValidationWithELInjectionRiskCausedByRecklessConcatenation, MyObjectWithELInjectionRiskCausedByRecklessConcatenation> {
+
+ @Override
+ public boolean isValid(MyObjectWithELInjectionRiskCausedByRecklessConcatenation value, ConstraintValidatorContext context) {
+ context.disableDefaultConstraintViolation();
+
+ // This is bad practice: message parameters should be used instead.
+ // Regardless, it can happen and should work as well as possible.
+ context.buildConstraintViolationWithTemplate( "Value '" + escape( value.field1 ) + "' is invalid" )
+ .addConstraintViolation();
+
+ return false;
+ }
+
+ private String escape(String value) {
+ return value.replaceAll( "\\$+\\{", "{" );
+ }
+ }
+ }
}

441
CVE-2020-10693-pre.patch Normal file
View File

@ -0,0 +1,441 @@
From 72049532fa289d0f5664e9b1a7fd19fd514e595f Mon Sep 17 00:00:00 2001
From: Gunnar Morling <gunnar.morling@googlemail.com>
Date: Wed, 31 Aug 2016 15:28:25 +0200
Subject: [PATCH] HV-1091 Using iterative instead of recursive approach for
message parsing
---
.../parser/BeginState.java | 12 +--
.../messageinterpolation/parser/ELState.java | 10 ---
.../parser/EscapedState.java | 9 --
.../parser/InterpolationTermState.java | 12 ---
.../parser/MessageState.java | 11 ---
.../parser/ParserState.java | 2 -
.../parser/TokenCollector.java | 16 ++--
.../validator/bugs/TooBigMessageTest.java | 90 +++++++++++++++++++
.../TokenIteratorTest.java | 8 +-
9 files changed, 103 insertions(+), 67 deletions(-)
create mode 100644 engine/src/test/java/org/hibernate/validator/bugs/TooBigMessageTest.java
diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/BeginState.java b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/BeginState.java
index 678f16e46..5aee73b9f 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/BeginState.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/BeginState.java
@@ -18,11 +18,7 @@
@Override
public void terminate(TokenCollector tokenCollector) throws MessageDescriptorFormatException {
- }
-
- @Override
- public void start(TokenCollector tokenCollector) throws MessageDescriptorFormatException {
- tokenCollector.next();
+ tokenCollector.terminateToken();
}
@Override
@@ -30,7 +26,6 @@ public void handleNonMetaCharacter(char character, TokenCollector tokenCollector
throws MessageDescriptorFormatException {
tokenCollector.appendToToken( character );
tokenCollector.transitionState( new MessageState() );
- tokenCollector.next();
}
@Override
@@ -43,7 +38,6 @@ public void handleBeginTerm(char character, TokenCollector tokenCollector) throw
tokenCollector.makeParameterToken();
}
tokenCollector.transitionState( new InterpolationTermState() );
- tokenCollector.next();
}
@Override
@@ -56,7 +50,6 @@ public void handleEscapeCharacter(char character, TokenCollector tokenCollector)
throws MessageDescriptorFormatException {
tokenCollector.appendToToken( character );
tokenCollector.transitionState( new EscapedState( this ) );
- tokenCollector.next();
}
@Override
@@ -68,9 +61,6 @@ public void handleELDesignator(char character, TokenCollector tokenCollector)
else {
ParserState state = new ELState();
tokenCollector.transitionState( state );
- tokenCollector.next();
}
}
}
-
-
diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/ELState.java b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/ELState.java
index ce7df402f..569ea1e2e 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/ELState.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/ELState.java
@@ -15,11 +15,6 @@
public class ELState implements ParserState {
private static final Log log = LoggerFactory.make();
- @Override
- public void start(TokenCollector tokenCollector) {
- throw new IllegalStateException( "Parsing of message descriptor cannot start in this state" );
- }
-
@Override
public void terminate(TokenCollector tokenCollector) throws MessageDescriptorFormatException {
tokenCollector.appendToToken( TokenCollector.EL_DESIGNATOR );
@@ -33,7 +28,6 @@ public void handleNonMetaCharacter(char character, TokenCollector tokenCollector
tokenCollector.appendToToken( character );
tokenCollector.terminateToken();
tokenCollector.transitionState( new BeginState() );
- tokenCollector.next();
}
@Override
@@ -44,7 +38,6 @@ public void handleBeginTerm(char character, TokenCollector tokenCollector) throw
tokenCollector.appendToToken( character );
tokenCollector.makeELToken();
tokenCollector.transitionState( new InterpolationTermState() );
- tokenCollector.next();
}
@Override
@@ -59,7 +52,6 @@ public void handleEndTerm(char character, TokenCollector tokenCollector) throws
public void handleEscapeCharacter(char character, TokenCollector tokenCollector)
throws MessageDescriptorFormatException {
tokenCollector.transitionState( new EscapedState( this ) );
- tokenCollector.next();
}
@Override
@@ -68,5 +60,3 @@ public void handleELDesignator(char character, TokenCollector tokenCollector)
handleNonMetaCharacter( character, tokenCollector );
}
}
-
-
diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/EscapedState.java b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/EscapedState.java
index 901acff4f..f44242dd1 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/EscapedState.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/EscapedState.java
@@ -16,11 +16,6 @@ public EscapedState(ParserState previousState) {
this.previousState = previousState;
}
- @Override
- public void start(TokenCollector tokenCollector) {
- throw new IllegalStateException( "Parsing of message descriptor cannot start in this state" );
- }
-
@Override
public void terminate(TokenCollector tokenCollector) throws MessageDescriptorFormatException {
tokenCollector.terminateToken();
@@ -58,9 +53,5 @@ private void handleEscapedCharacter(char character, TokenCollector tokenCollecto
throws MessageDescriptorFormatException {
tokenCollector.appendToToken( character );
tokenCollector.transitionState( previousState );
- tokenCollector.next();
}
}
-
-
-
diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/InterpolationTermState.java b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/InterpolationTermState.java
index f921113f9..11c974373 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/InterpolationTermState.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/InterpolationTermState.java
@@ -15,11 +15,6 @@
public class InterpolationTermState implements ParserState {
private static final Log log = LoggerFactory.make();
- @Override
- public void start(TokenCollector tokenCollector) {
- throw new IllegalStateException( "Parsing of message descriptor cannot start in this state" );
- }
-
@Override
public void terminate(TokenCollector tokenCollector) throws MessageDescriptorFormatException {
throw log.getNonTerminatedParameterException(
@@ -32,7 +27,6 @@ public void terminate(TokenCollector tokenCollector) throws MessageDescriptorFor
public void handleNonMetaCharacter(char character, TokenCollector tokenCollector)
throws MessageDescriptorFormatException {
tokenCollector.appendToToken( character );
- tokenCollector.next();
}
@Override
@@ -46,7 +40,6 @@ public void handleEndTerm(char character, TokenCollector tokenCollector) throws
tokenCollector.terminateToken();
BeginState beginState = new BeginState();
tokenCollector.transitionState( beginState );
- tokenCollector.next();
}
@Override
@@ -55,16 +48,11 @@ public void handleEscapeCharacter(char character, TokenCollector tokenCollector)
tokenCollector.appendToToken( character );
ParserState state = new EscapedState( this );
tokenCollector.transitionState( state );
- tokenCollector.next();
-
}
@Override
public void handleELDesignator(char character, TokenCollector tokenCollector)
throws MessageDescriptorFormatException {
tokenCollector.appendToToken( character );
- tokenCollector.next();
}
}
-
-
diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/MessageState.java b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/MessageState.java
index bac9c7e46..37cd23503 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/MessageState.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/MessageState.java
@@ -16,11 +16,6 @@
public class MessageState implements ParserState {
private static final Log log = LoggerFactory.make();
- @Override
- public void start(TokenCollector tokenCollector) {
- throw new IllegalStateException( "The parsing of the message descriptor cannot start in this state." );
- }
-
@Override
public void terminate(TokenCollector tokenCollector) throws MessageDescriptorFormatException {
tokenCollector.terminateToken();
@@ -30,7 +25,6 @@ public void terminate(TokenCollector tokenCollector) throws MessageDescriptorFor
public void handleNonMetaCharacter(char character, TokenCollector tokenCollector)
throws MessageDescriptorFormatException {
tokenCollector.appendToToken( character );
- tokenCollector.next();
}
@Override
@@ -42,7 +36,6 @@ public void handleBeginTerm(char character, TokenCollector tokenCollector) throw
tokenCollector.makeParameterToken();
}
tokenCollector.transitionState( new InterpolationTermState() );
- tokenCollector.next();
}
@Override
@@ -59,7 +52,6 @@ public void handleEscapeCharacter(char character, TokenCollector tokenCollector)
tokenCollector.appendToToken( character );
tokenCollector.transitionState( new EscapedState( this ) );
- tokenCollector.next();
}
@Override
@@ -70,9 +62,6 @@ public void handleELDesignator(char character, TokenCollector tokenCollector)
}
else {
tokenCollector.transitionState( new ELState() );
- tokenCollector.next();
}
}
}
-
-
diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/ParserState.java b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/ParserState.java
index a48a48f2b..64317de46 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/ParserState.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/ParserState.java
@@ -13,7 +13,6 @@
* @author Hardy Ferentschik
*/
public interface ParserState {
- void start(TokenCollector tokenCollector) throws MessageDescriptorFormatException;
void terminate(TokenCollector tokenCollector) throws MessageDescriptorFormatException;
@@ -27,4 +26,3 @@
void handleELDesignator(char character, TokenCollector tokenCollector) throws MessageDescriptorFormatException;
}
-
diff --git a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/TokenCollector.java b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/TokenCollector.java
index 1443eee7f..ffce7bb68 100644
--- a/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/TokenCollector.java
+++ b/engine/src/main/java/org/hibernate/validator/internal/engine/messageinterpolation/parser/TokenCollector.java
@@ -6,13 +6,13 @@
*/
package org.hibernate.validator.internal.engine.messageinterpolation.parser;
+import static org.hibernate.validator.internal.util.CollectionHelper.newArrayList;
+
import java.util.Collections;
import java.util.List;
import org.hibernate.validator.internal.engine.messageinterpolation.InterpolationTermType;
-import static org.hibernate.validator.internal.util.CollectionHelper.newArrayList;
-
/**
* Used to creates a list of tokens from a message descriptor.
*
@@ -28,7 +28,7 @@
private final String originalMessageDescriptor;
private final InterpolationTermType interpolationTermType;
- private List<Token> tokenList;
+ private final List<Token> tokenList;
private ParserState currentParserState;
private int currentPosition;
private Token currentToken;
@@ -69,10 +69,11 @@ public void makeELToken() {
currentToken.makeELToken();
}
- public void next() throws MessageDescriptorFormatException {
+ private void next() throws MessageDescriptorFormatException {
if ( currentPosition == originalMessageDescriptor.length() ) {
// give the current context the chance to complete
currentParserState.terminate( this );
+ currentPosition++;
return;
}
char currentCharacter = originalMessageDescriptor.charAt( currentPosition );
@@ -98,12 +99,12 @@ public void next() throws MessageDescriptorFormatException {
currentParserState.handleNonMetaCharacter( currentCharacter, this );
}
}
- // make sure the last token is terminated
- terminateToken();
}
public void parse() throws MessageDescriptorFormatException {
- currentParserState.start( this );
+ while ( currentPosition <= originalMessageDescriptor.length() ) {
+ next();
+ }
}
public void transitionState(ParserState newState) {
@@ -122,4 +123,3 @@ public String getOriginalMessageDescriptor() {
return originalMessageDescriptor;
}
}
-
diff --git a/engine/src/test/java/org/hibernate/validator/bugs/TooBigMessageTest.java b/engine/src/test/java/org/hibernate/validator/bugs/TooBigMessageTest.java
new file mode 100644
index 000000000..4eb8ffc18
--- /dev/null
+++ b/engine/src/test/java/org/hibernate/validator/bugs/TooBigMessageTest.java
@@ -0,0 +1,90 @@
+/*
+ * Hibernate Validator, declare and validate application constraints
+ *
+ * License: Apache License, Version 2.0
+ * See the license.txt file in the root directory or <http://www.apache.org/licenses/LICENSE-2.0>.
+ */
+package org.hibernate.validator.bugs;
+
+import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertCorrectConstraintViolationMessages;
+import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertNumberOfViolations;
+
+import java.util.Set;
+
+import javax.validation.ConstraintViolation;
+import javax.validation.Validator;
+import javax.validation.constraints.NotNull;
+
+import org.hibernate.validator.testutil.TestForIssue;
+import org.hibernate.validator.testutils.ValidatorUtil;
+import org.junit.Test;
+
+/**
+ * Ensure large error messages can be interpolated.
+ *
+ * @author Gunnar Morling
+ */
+public class TooBigMessageTest {
+
+ /**
+ * Large enough to trigger a stack overflow with the recursive scheme, assuming default settings
+ */
+ private static final String LARGE_MESSAGE =
+ "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ + "12345678901234567890123456789012345678901234567890123456789012345678901234567890";
+
+ @Test
+ @TestForIssue(jiraKey = "HV-1091")
+ public void largeMessageCanBeInterpolated() {
+ Validator validator = ValidatorUtil.getValidator();
+ GoldFish fish = new GoldFish();
+
+ Set<ConstraintViolation<GoldFish>> constraintViolations = validator.validate( fish );
+ assertNumberOfViolations( constraintViolations, 1 );
+ assertCorrectConstraintViolationMessages( constraintViolations, LARGE_MESSAGE );
+ }
+
+ private static class GoldFish {
+
+ @NotNull(message = LARGE_MESSAGE)
+ String name;
+ }
+}
diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenIteratorTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenIteratorTest.java
index a63e1996a..281f3bccf 100644
--- a/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenIteratorTest.java
+++ b/engine/src/test/java/org/hibernate/validator/test/internal/engine/messageinterpolation/TokenIteratorTest.java
@@ -6,15 +6,15 @@
*/
package org.hibernate.validator.test.internal.engine.messageinterpolation;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
import org.hibernate.validator.internal.engine.messageinterpolation.InterpolationTermType;
import org.hibernate.validator.internal.engine.messageinterpolation.parser.TokenCollector;
import org.hibernate.validator.internal.engine.messageinterpolation.parser.TokenIterator;
import org.testng.annotations.Test;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertTrue;
-
/**
* Tests for {@code TokenIterator}.
*

View File

@ -4,7 +4,7 @@
Name: hibernate-validator
Version: 5.2.4
Release: 2
Release: 3
Summary: Bean Validation 1.1 (JSR 349) Reference Implementation
License: ASL 2.0
URL: http://www.hibernate.org/subprojects/validator.html
@ -12,6 +12,11 @@ Source0: https://github.com/hibernate/hibernate-validator/archive/%{
# JAXB2 and JDK7+ problems see https://hibernate.atlassian.net/browse/HV-528
Patch0: %{name}-5.2.4.Final-jaxb.patch
Patch1: CVE-2017-7536.patch
Patch2: CVE-2020-10693-pre.patch
Patch3: CVE-2020-10693-1.patch
Patch4: CVE-2020-10693-2.patch
Patch5: CVE-2020-10693-3.patch
Patch6: CVE-2020-10693-4.patch
BuildRequires: maven-local mvn(com.fasterxml:classmate) mvn(com.sun.xml.bind:jaxb-impl)
BuildRequires: mvn(com.thoughtworks.paranamer:paranamer)
@ -76,6 +81,11 @@ This package contains javadoc for %{name}.
find . -name "*.jar" -delete
%patch0 -p1
%patch1 -p1
%patch2 -p1
%patch3 -p1
%patch4 -p1
%patch5 -p1
%patch6 -p1
%pom_disable_module distribution
%pom_disable_module documentation
%pom_disable_module engine-jdk8-tests
@ -132,6 +142,9 @@ rm engine/src/main/java/org/hibernate/validator/internal/engine/valuehandling/Ja
%license copyright.txt license.txt
%changelog
* Mon Mar 15 2021 wangxiao <wangxiao65@huawei.com> - 5.2.4-3
- Fix CVE-2020-10693
* Sat Sep 19 2020 maminjie <maminjie1@huawei.com> - 5.2.4-2
- fix CVE-2017-7536