-
Notifications
You must be signed in to change notification settings - Fork 16
Description
Description
MessageOneofEvaluator.evaluate() calls Message.hasField(field) on every field in its field list (MessageOneofEvaluator.java:54). In protobuf-java, hasField() throws UnsupportedOperationException when invoked on a repeated or map field because presence is not a concept that applies to them. If a MessageOneofRule references a repeated or map field by name, the evaluator will crash at runtime instead of producing a validation result.
Steps to Reproduce
- Define a protobuf message with at least one repeated (or map) field and a
MessageOneofRulethat includes that field:message Example { option (buf.validate.message).oneof = { fields: ["name", "tags"] required: true }; string name = 1; repeated string tags = 2; }
- Build a
Validatorand validate any instance ofExample. - Observe the exception during evaluation.
Expected Behavior
The MessageOneofRule should work as documented — validating that at most one (or exactly one, if required) of the specified fields is set, regardless of whether the fields are singular, repeated, or map types.
Actual Behavior
An UnsupportedOperationException is thrown at runtime
Screenshots/Logs
java.lang.UnsupportedOperationException: hasField() called on a repeated field.
at com.google.protobuf.GeneratedMessage.hasField(GeneratedMessage.java:255)
at build.buf.protovalidate.MessageOneofEvaluator.evaluate(MessageOneofEvaluator.java:54)
Environment
- Operating System: macOS
- Version: Darwin 25.3.0
- Compiler/Toolchain: JDK 21+, Gradle 9.3.1
- Protobuf Compiler & Version: buf v1.66.0, protobuf-java 4.34.0
- Protovalidate Version: v1.1.0
Possible Solution
In MessageOneofEvaluator.evaluate(), check whether the field is repeated before calling hasField(), and use an appropriate presence check instead:
for (FieldDescriptor field : fields) {
boolean isSet = field.isRepeated()
? msg.getRepeatedFieldCount(field) > 0
: msg.hasField(field);
if (isSet) {
hasCount++;
}
}Additional Context
The fix should be tested thoroughly across all protobuf field types — singular scalars, message fields, repeated fields, and map fields — to ensure MessageOneofEvaluator correctly determines presence for each.