Skip to content

Commit 63c73f3

Browse files
committed
Reject unbalanced parentheses in profile expressions
ProfilesParser.parseTokens() silently accepts unbalanced parentheses in profile expressions such as "dev)" or "(dev", treating them as valid. This can lead to unexpected behavior where malformed @Profile annotations are silently interpreted instead of being rejected. This commit tightens the validation in parseTokens() to reject: - Unmatched closing parenthesis at the top level - Unmatched opening parenthesis when tokens are exhausted Also fixes an existing test that inadvertently relied on this lenient behavior by using "spring&framework)" instead of "(spring&framework)". Fixes gh-36540
1 parent 5708b73 commit 63c73f3

File tree

2 files changed

+13
-6
lines changed

2 files changed

+13
-6
lines changed

spring-core/src/main/java/org/springframework/core/env/ProfilesParser.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,10 @@ private static Profiles parseTokens(String expression, StringTokenizer tokens, C
8888
}
8989
case "!" -> elements.add(not(parseTokens(expression, tokens, Context.NEGATE)));
9090
case ")" -> {
91-
Profiles merged = merge(expression, elements, operator);
9291
if (context == Context.PARENTHESIS) {
93-
return merged;
92+
return merge(expression, elements, operator);
9493
}
95-
elements.clear();
96-
elements.add(merged);
97-
operator = null;
94+
assertWellFormed(expression, false);
9895
}
9996
default -> {
10097
Profiles value = equals(token);
@@ -105,6 +102,7 @@ private static Profiles parseTokens(String expression, StringTokenizer tokens, C
105102
}
106103
}
107104
}
105+
assertWellFormed(expression, context != Context.PARENTHESIS);
108106
return merge(expression, elements, operator);
109107
}
110108

spring-core/src/test/java/org/springframework/core/env/ProfilesTests.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ void ofAndExpression() {
155155

156156
@Test
157157
void ofAndExpressionWithoutSpaces() {
158-
Profiles profiles = Profiles.of("spring&framework)");
158+
Profiles profiles = Profiles.of("(spring&framework)");
159159
assertAndExpression(profiles);
160160
}
161161

@@ -292,6 +292,15 @@ void malformedExpressions() {
292292
assertMalformed(() -> Profiles.of("a & b | c"));
293293
}
294294

295+
@Test
296+
void malformedExpressionsWithUnbalancedParentheses() {
297+
assertMalformed(() -> Profiles.of("dev)"));
298+
assertMalformed(() -> Profiles.of("(dev"));
299+
assertMalformed(() -> Profiles.of("spring&framework)"));
300+
assertMalformed(() -> Profiles.of("((dev)"));
301+
assertMalformed(() -> Profiles.of("(dev))"));
302+
}
303+
295304
@Test
296305
void sensibleToString() {
297306
assertThat(Profiles.of("spring")).hasToString("spring");

0 commit comments

Comments
 (0)