Skip to content

Commit 38c11be

Browse files
committed
fix(openfeature): return PARSE_ERROR for invalid regex in flag condition
1 parent 071ce9d commit 38c11be

2 files changed

Lines changed: 30 additions & 7 deletions

File tree

products/feature-flagging/feature-flagging-api/src/main/java/datadog/trace/api/openfeature/DDEvaluator.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import java.util.concurrent.TimeUnit;
4040
import java.util.concurrent.atomic.AtomicReference;
4141
import java.util.regex.Pattern;
42+
import java.util.regex.PatternSyntaxException;
4243

4344
class DDEvaluator implements Evaluator, FeatureFlaggingGateway.ConfigListener {
4445

@@ -148,6 +149,8 @@ public <T> ProviderEvaluation<T> evaluate(
148149
.value(defaultValue)
149150
.reason(Reason.DEFAULT.name())
150151
.build();
152+
} catch (final PatternSyntaxException e) {
153+
return error(defaultValue, ErrorCode.PARSE_ERROR, e);
151154
} catch (final NumberFormatException e) {
152155
return error(defaultValue, ErrorCode.TYPE_MISMATCH, e);
153156
} catch (final Exception e) {
@@ -251,12 +254,10 @@ private static boolean evaluateCondition(
251254
}
252255

253256
private static boolean matchesRegex(final Object attributeValue, final Object conditionValue) {
254-
try {
255-
final Pattern pattern = Pattern.compile(String.valueOf(conditionValue));
256-
return pattern.matcher(String.valueOf(attributeValue)).find();
257-
} catch (Exception e) {
258-
return false;
259-
}
257+
// PatternSyntaxException is intentionally not caught here so it propagates to evaluate(),
258+
// which maps it to ErrorCode.PARSE_ERROR.
259+
final Pattern pattern = Pattern.compile(String.valueOf(conditionValue));
260+
return pattern.matcher(String.valueOf(attributeValue)).find();
260261
}
261262

262263
private static boolean isOneOf(final Object attributeValue, final Object conditionValue) {

products/feature-flagging/feature-flagging-api/src/test/java/datadog/trace/api/openfeature/DDEvaluatorTest.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,12 @@ private static List<TestCase<?>> evaluateTestCases() {
489489
.result(
490490
new Result<>("null-handled")
491491
.reason(TARGETING_MATCH.name())
492-
.variant("null-variant")));
492+
.variant("null-variant")),
493+
new TestCase<>("default")
494+
.flag("invalid-regex-flag")
495+
.targetingKey("user-123")
496+
.context("email", "user@example.com")
497+
.result(new Result<>("default").reason(ERROR.name()).errorCode(ErrorCode.PARSE_ERROR)));
493498
}
494499

495500
@MethodSource("evaluateTestCases")
@@ -581,6 +586,7 @@ private ServerConfiguration createTestConfiguration() {
581586
flags.put(
582587
"integer-string-variant-flag",
583588
createSimpleFlag("integer-string-variant-flag", ValueType.INTEGER, "not-a-number", "bad"));
589+
flags.put("invalid-regex-flag", createInvalidRegexFlag());
584590
return new ServerConfiguration(null, null, null, flags);
585591
}
586592

@@ -1266,6 +1272,22 @@ private Flag createCountryRuleFlag() {
12661272
asList(usAllocation, globalAllocation));
12671273
}
12681274

1275+
private Flag createInvalidRegexFlag() {
1276+
final Map<String, Variant> variants = new HashMap<>();
1277+
variants.put("matched", new Variant("matched", "matched-value"));
1278+
1279+
// Condition with an intentionally invalid regex pattern (unclosed bracket)
1280+
final List<ConditionConfiguration> conditions =
1281+
singletonList(new ConditionConfiguration(ConditionOperator.MATCHES, "email", "[invalid"));
1282+
final List<Rule> rules = singletonList(new Rule(conditions));
1283+
final List<Split> splits = singletonList(new Split(emptyList(), "matched", null));
1284+
final Allocation allocation =
1285+
new Allocation("invalid-regex-alloc", rules, null, null, splits, false);
1286+
1287+
return new Flag(
1288+
"invalid-regex-flag", true, ValueType.STRING, variants, singletonList(allocation));
1289+
}
1290+
12691291
private static Map<String, Object> mapOf(final Object... props) {
12701292
final Map<String, Object> result = new HashMap<>(props.length << 1);
12711293
int index = 0;

0 commit comments

Comments
 (0)