-
Notifications
You must be signed in to change notification settings - Fork 15.9k
Description
What version of protobuf and what language are you using?
Language: Ruby 2.6.2
Version: google-protobuf-3.11.4-x86_64-linux
What did you do?
Steps to reproduce the behavior:
- Generate ruby code for the following message:
syntax = "proto3";
package sample;
message SampleMessage {
oneof value {
google.protobuf.StringValue string = 1;
google.protobuf.Int32Value int = 2;
}
}
- Initialize a message with a default value (empty string or zero) for either of the oneof fields:
msg = Sample::SampleMessage.new(string: Google::Protobuf::StringValue.new(value: ""))
# #<Sample::SampleMessage string: <Google::Protobuf::StringValue value: "">, int: nil>
- Encode the message to protobuf:
msg.to_proto
# "\x0a\x00"
- Decode the resulting bytes
Sample::SampleMessage.decode("\x0a\x00")
# #<Sample::FooDto:0x2ad3d4d00b38>
What did you expect to see
The decoded protobuf should be identical to the message before encoding.
What did you see instead?
The decoded protobuf is left in an inconsistent state without the oneof value having been initialized. Attempting to access the string value results in a confusing exception:
Sample::SampleMessage.decode("\x0a\x00").string
# Google::Protobuf::TypeError: Invalid argument for string field 'value' (given FalseClass).
Anything else we should know about your project / environment
This issue only appears when using well-known types StringWrapper
, Int32Wrapper
, Int64Wrapper
, and FloatWrapper
. BoolWrapper
is not affected, for whatever reason. Similarly, substituting the Google protobuf wrappers with home-grown wrappers (e.g., a simple message with a single primitive field) does not exhibit this issue.
Attempting to decode the slightly-modified protobuf format "\x0a\x02\x0a\x00"
does result in the expected message, which leads me to believe that the issue lies specifically in attempting to populate a default (0-byte) value for a well-known type when decoding a oneof field.
We were able to get around this issue in our project by updating our oneof to use only primitive fields rather than wrappers (the wrappers are pointless in this case because we can't set a oneof to nil
), but this still seems like undesirable behavior.