Skip to content

Commit cff6d49

Browse files
l46kokcopybara-github
authored andcommitted
Add CelOptions to disable string conversion and list/string concatenation
Fixes #502 PiperOrigin-RevId: 700727733
1 parent e104ba7 commit cff6d49

4 files changed

Lines changed: 96 additions & 4 deletions

File tree

bundle/src/test/java/dev/cel/bundle/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ java_library(
1818
"//checker:proto_type_mask",
1919
"//common",
2020
"//common:compiler_common",
21+
"//common:error_codes",
2122
"//common:options",
2223
"//common:proto_ast",
2324
"//common/ast",

bundle/src/test/java/dev/cel/bundle/CelImplTest.java

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
import dev.cel.checker.ProtoTypeMask;
6464
import dev.cel.checker.TypeProvider;
6565
import dev.cel.common.CelAbstractSyntaxTree;
66+
import dev.cel.common.CelErrorCode;
6667
import dev.cel.common.CelIssue;
6768
import dev.cel.common.CelOptions;
6869
import dev.cel.common.CelProtoAbstractSyntaxTree;
@@ -1961,6 +1962,59 @@ public void program_nativeTypeUnknownsEnabled_asCallArguments() throws Exception
19611962
assertThat(result.attributes()).isEmpty();
19621963
}
19631964

1965+
@Test
1966+
@TestParameters("{expression: 'string(123)'}")
1967+
@TestParameters("{expression: 'string(123u)'}")
1968+
@TestParameters("{expression: 'string(1.5)'}")
1969+
@TestParameters("{expression: 'string(\"foo\")'}")
1970+
@TestParameters("{expression: 'string(b\"foo\")'}")
1971+
@TestParameters("{expression: 'string(timestamp(100))'}")
1972+
@TestParameters("{expression: 'string(duration(\"1h\"))'}")
1973+
public void program_stringConversionDisabled_throws(String expression) throws Exception {
1974+
Cel cel =
1975+
CelFactory.standardCelBuilder()
1976+
.setOptions(
1977+
CelOptions.current()
1978+
.enableTimestampEpoch(true)
1979+
.enableStringConversion(false)
1980+
.build())
1981+
.build();
1982+
CelAbstractSyntaxTree ast = cel.compile(expression).getAst();
1983+
1984+
CelEvaluationException e =
1985+
assertThrows(CelEvaluationException.class, () -> cel.createProgram(ast).eval());
1986+
assertThat(e).hasMessageThat().contains("No matching overload for function 'string'");
1987+
assertThat(e.getErrorCode()).isEqualTo(CelErrorCode.OVERLOAD_NOT_FOUND);
1988+
}
1989+
1990+
@Test
1991+
public void program_stringConcatenationDisabled_throws() throws Exception {
1992+
Cel cel =
1993+
CelFactory.standardCelBuilder()
1994+
.setOptions(CelOptions.current().enableStringConcatenation(false).build())
1995+
.build();
1996+
CelAbstractSyntaxTree ast = cel.compile("'foo' + 'bar'").getAst();
1997+
1998+
CelEvaluationException e =
1999+
assertThrows(CelEvaluationException.class, () -> cel.createProgram(ast).eval());
2000+
assertThat(e).hasMessageThat().contains("No matching overload for function '_+_'");
2001+
assertThat(e.getErrorCode()).isEqualTo(CelErrorCode.OVERLOAD_NOT_FOUND);
2002+
}
2003+
2004+
@Test
2005+
public void program_listConcatenationDisabled_throws() throws Exception {
2006+
Cel cel =
2007+
CelFactory.standardCelBuilder()
2008+
.setOptions(CelOptions.current().enableListConcatenation(false).build())
2009+
.build();
2010+
CelAbstractSyntaxTree ast = cel.compile("[1] + [2]").getAst();
2011+
2012+
CelEvaluationException e =
2013+
assertThrows(CelEvaluationException.class, () -> cel.createProgram(ast).eval());
2014+
assertThat(e).hasMessageThat().contains("No matching overload for function '_+_'");
2015+
assertThat(e.getErrorCode()).isEqualTo(CelErrorCode.OVERLOAD_NOT_FOUND);
2016+
}
2017+
19642018
@Test
19652019
public void toBuilder_isImmutable() {
19662020
CelBuilder celBuilder = CelFactory.standardCelBuilder();

common/src/main/java/dev/cel/common/CelOptions.java

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,12 @@ public enum ProtoUnsetFieldOptions {
109109

110110
public abstract ProtoUnsetFieldOptions fromProtoUnsetFieldOption();
111111

112+
public abstract boolean enableStringConversion();
113+
114+
public abstract boolean enableStringConcatenation();
115+
116+
public abstract boolean enableListConcatenation();
117+
112118
public abstract Builder toBuilder();
113119

114120
public ImmutableSet<ExprFeatures> toExprFeatures() {
@@ -200,7 +206,10 @@ public static Builder newBuilder() {
200206
.enableCelValue(false)
201207
.comprehensionMaxIterations(-1)
202208
.unwrapWellKnownTypesOnFunctionDispatch(true)
203-
.fromProtoUnsetFieldOption(ProtoUnsetFieldOptions.BIND_DEFAULT);
209+
.fromProtoUnsetFieldOption(ProtoUnsetFieldOptions.BIND_DEFAULT)
210+
.enableStringConversion(true)
211+
.enableStringConcatenation(true)
212+
.enableListConcatenation(true);
204213
}
205214

206215
/**
@@ -504,6 +513,24 @@ public abstract static class Builder {
504513
*/
505514
public abstract Builder fromProtoUnsetFieldOption(ProtoUnsetFieldOptions value);
506515

516+
/**
517+
* Enables string() overloads for the runtime. This option exists to maintain parity with
518+
* cel-cpp interpreter options.
519+
*/
520+
public abstract Builder enableStringConversion(boolean value);
521+
522+
/**
523+
* Enables string concatenation overload for the runtime. This option exists to maintain parity
524+
* with cel-cpp interpreter options.
525+
*/
526+
public abstract Builder enableStringConcatenation(boolean value);
527+
528+
/**
529+
* Enables list concatenation overload for the runtime. This option exists to maintain parity
530+
* with cel-cpp interpreter options.
531+
*/
532+
public abstract Builder enableListConcatenation(boolean value);
533+
507534
public abstract CelOptions build();
508535
}
509536
}

runtime/src/main/java/dev/cel/runtime/CelRuntimeLegacyImpl.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import dev.cel.common.types.CelTypes;
4444
import dev.cel.common.values.CelValueProvider;
4545
import dev.cel.common.values.ProtoMessageValueProvider;
46+
import dev.cel.runtime.CelStandardFunctions.StandardFunction.Overload.Arithmetic;
4647
import dev.cel.runtime.CelStandardFunctions.StandardFunction.Overload.Comparison;
4748
import dev.cel.runtime.CelStandardFunctions.StandardFunction.Overload.Conversions;
4849
import java.util.Arrays;
@@ -317,13 +318,22 @@ private ImmutableSet<CelFunctionBinding> newStandardFunctionBindings(
317318
return options.enableTimestampEpoch();
318319
}
319320
break;
321+
case STRING:
322+
return options.enableStringConversion();
323+
case ADD:
324+
Arithmetic arithmetic = (Arithmetic) standardOverload;
325+
if (arithmetic.equals(Arithmetic.ADD_STRING)) {
326+
return options.enableStringConcatenation();
327+
}
328+
if (arithmetic.equals(Arithmetic.ADD_LIST)) {
329+
return options.enableListConcatenation();
330+
}
331+
break;
320332
default:
321333
if (standardOverload instanceof Comparison
322334
&& !options.enableHeterogeneousNumericComparisons()) {
323335
Comparison comparison = (Comparison) standardOverload;
324-
if (comparison.isHeterogeneousComparison()) {
325-
return false;
326-
}
336+
return !comparison.isHeterogeneousComparison();
327337
}
328338
break;
329339
}

0 commit comments

Comments
 (0)