Summary
Wire's ProtoAdapter for google.protobuf.Timestamp does not validate that Instant values fall within the protobuf spec's valid range (0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z). Out-of-range values like Instant.MIN are silently serialized, producing messages that are technically invalid per the protobuf spec.
These invalid messages decode fine (the wire format is just int64), but blow up downstream when any code calls Timestamps.checkValid() or Timestamps.toMillis() — for example, Confluent's ProtobufData converter.
Reproducer
import com.squareup.wire.ProtoAdapter
import com.squareup.wire.ofEpochSecond
import java.time.Instant
// This succeeds — but the resulting bytes contain an invalid Timestamp
val instant = ofEpochSecond(Instant.MIN.epochSecond, 0L)
val bytes = ProtoAdapter.INSTANT.encode(instant)
// Round-trip through Wire works fine (no validation)
val decoded = ProtoAdapter.INSTANT.decode(bytes)
println(decoded.getEpochSecond()) // -31557014167219200
// But Google's protobuf-java-util rejects it
val timestamp = com.google.protobuf.Timestamp.newBuilder()
.setSeconds(decoded.getEpochSecond())
.build()
com.google.protobuf.util.Timestamps.toMillis(timestamp) // throws IllegalArgumentException
java.lang.IllegalArgumentException: Timestamp is not valid.
Seconds (-31557014167219200) must be in range [-62,135,596,800, +253,402,300,799].
Affected code
ProtoAdapter.kt line 1295-1300:
override fun encode(writer: ProtoWriter, value: Instant) {
val seconds = value.getEpochSecond()
if (seconds != 0L) INT64.encodeWithTag(writer, 1, seconds)
val nanos = value.getNano()
if (nanos != 0) INT32.encodeWithTag(writer, 2, nanos)
}
No range check on seconds.
Suggestion
Validate during Timestamp().build() that seconds and nanos are within (protobuf spec) range, throwing IllegalArgumentException they aren't.
Or, perform that validation during encode().
This would catch bugs at the point of serialization rather than letting invalid data propagate silently.
Summary
Wire's
ProtoAdapterforgoogle.protobuf.Timestampdoes not validate thatInstantvalues fall within the protobuf spec's valid range (0001-01-01T00:00:00Zto9999-12-31T23:59:59.999999999Z). Out-of-range values likeInstant.MINare silently serialized, producing messages that are technically invalid per the protobuf spec.These invalid messages decode fine (the wire format is just
int64), but blow up downstream when any code callsTimestamps.checkValid()orTimestamps.toMillis()— for example, Confluent'sProtobufDataconverter.Reproducer
Affected code
ProtoAdapter.ktline 1295-1300:No range check on
seconds.Suggestion
Validate during
Timestamp().build()thatsecondsandnanosare within (protobuf spec) range, throwingIllegalArgumentExceptionthey aren't.Or, perform that validation during
encode().This would catch bugs at the point of serialization rather than letting invalid data propagate silently.