Skip to content

Commit f17fd65

Browse files
authored
Override bytes_to_string (#304)
Override `bytes_to_string` to validate utf-8 --------- Signed-off-by: Sri Krishna <[email protected]>
1 parent 3c060a2 commit f17fd65

File tree

3 files changed

+38
-10
lines changed

3 files changed

+38
-10
lines changed

conformance/expected-failures.yaml

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +0,0 @@
1-
standard_rules/bytes:
2-
- pattern/invalid/not_utf8
3-
# input: [ type.googleapis.com/buf.validate.conformance.cases.BytesPattern ]:{val:"\x99"}
4-
# want: runtime error: value must be valid UTF-8 to apply regexp
5-
# got: validation error (1 violation)
6-
# 1. rule_id: "bytes.pattern"
7-
# message: "value must match regex pattern `^[\\x00-\\x7F]+$`"
8-
# field: "val" elements:{field_number:1 field_name:"val" field_type:TYPE_BYTES}
9-
# rule: "bytes.pattern" elements:{field_number:15 field_name:"bytes" field_type:TYPE_MESSAGE} elements:{field_number:4 field_name:"pattern" field_type:TYPE_STRING}

src/main/java/build/buf/protovalidate/CustomOverload.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
import com.google.protobuf.ByteString;
1818
import com.google.protobuf.Descriptors;
1919
import com.google.protobuf.Message;
20+
import dev.cel.common.CelErrorCode;
21+
import dev.cel.common.CelRuntimeException;
2022
import dev.cel.common.types.CelType;
2123
import dev.cel.common.types.SimpleType;
2224
import dev.cel.runtime.CelEvaluationException;
@@ -47,6 +49,7 @@ static List<CelFunctionBinding> create() {
4749
ArrayList<CelFunctionBinding> bindings = new ArrayList<>();
4850
bindings.addAll(
4951
Arrays.asList(
52+
celBytesToString(),
5053
celGetField(),
5154
celFormat(),
5255
celStartsWithBytes(),
@@ -70,6 +73,26 @@ static List<CelFunctionBinding> create() {
7073
return Collections.unmodifiableList(bindings);
7174
}
7275

76+
/**
77+
* This implementes that standard {@code bytes_to_string} function. We override it because the CEL
78+
* library doesn't validate that the bytes are valid utf-8.
79+
*
80+
* <p>Workround until https://github.com/google/cel-java/pull/717 lands.
81+
*/
82+
private static CelFunctionBinding celBytesToString() {
83+
return CelFunctionBinding.from(
84+
"bytes_to_string",
85+
ByteString.class,
86+
v -> {
87+
if (!v.isValidUtf8()) {
88+
throw new CelRuntimeException(
89+
new IllegalArgumentException("invalid UTF-8 in bytes, cannot convert to string"),
90+
CelErrorCode.BAD_FORMAT);
91+
}
92+
return v.toStringUtf8();
93+
});
94+
}
95+
7396
/**
7497
* Creates a custom function overload for the "getField" operation.
7598
*

src/main/java/build/buf/protovalidate/ValidateLibrary.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
import dev.cel.parser.CelStandardMacro;
2323
import dev.cel.runtime.CelRuntimeBuilder;
2424
import dev.cel.runtime.CelRuntimeLibrary;
25+
import dev.cel.runtime.CelStandardFunctions;
26+
import dev.cel.runtime.CelStandardFunctions.StandardFunction;
27+
import dev.cel.runtime.CelStandardFunctions.StandardFunction.Overload.Conversions;
2528

2629
/**
2730
* Custom {@link CelCompilerLibrary} and {@link CelRuntimeLibrary}. Provides all the custom
@@ -54,6 +57,17 @@ public void setCheckerOptions(CelCheckerBuilder checkerBuilder) {
5457

5558
@Override
5659
public void setRuntimeOptions(CelRuntimeBuilder runtimeBuilder) {
57-
runtimeBuilder.addFunctionBindings(CustomOverload.create());
60+
runtimeBuilder
61+
.addFunctionBindings(CustomOverload.create())
62+
.setStandardEnvironmentEnabled(false)
63+
.setStandardFunctions(
64+
CelStandardFunctions.newBuilder()
65+
.filterFunctions(
66+
// CEL doesn't validate, that the bytes are valid utf-8, so we provide out own
67+
// implementation.
68+
(function, overload) ->
69+
function != StandardFunction.STRING
70+
|| !overload.equals(Conversions.BYTES_TO_STRING))
71+
.build());
5872
}
5973
}

0 commit comments

Comments
 (0)