Skip to content

Ruby Oneof Fields WellKnownType Fields with Default Values Don't Decode Properly #7889

@TedStudley

Description

@TedStudley

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:

  1. 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;
  }
}
  1. 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>
  1. Encode the message to protobuf:
msg.to_proto
# "\x0a\x00"
  1. 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.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions