Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proto3 compatibility: use uvarint encoding in time instead of fixed sized #224

Merged
merged 6 commits into from
Oct 14, 2018

Conversation

liamsi
Copy link
Contributor

@liamsi liamsi commented Sep 6, 2018

WIP: fuzzer found a crasher, still need to investigate if this is related!
The fuzzer just timed out, no real crashers.

resolves #208
resolves #223

 - internal seconds and nanos were encoded fixed size which is different
 from proto's "well known type" TimeStamp
@liamsi
Copy link
Contributor Author

liamsi commented Sep 8, 2018

This is actually a bit confusing:
proto3's Timestamp message looks like this:

message Timestamp {
  int64 seconds = 1; // this is proto3's int64
  int32 nanos = 2;
}

which translate into this go code:

type Timestamp struct {
	Seconds int64 `protobuf:"varint,1,opt,name=seconds,proto3" json:"seconds,omitempty"`
	Nanos   int32    `protobuf:"varint,2,opt,name=nanos,proto3" json:"nanos,omitempty"`
}

In protobuf int32 and int64 are casted to uint64 and encoded as unsigned varint. In amino we encode golang's int32 as varint (not unsigned). We treat it as proto's sint32 which is encoded differently (see scalar types). This isn't a problem but probably needs to be documented somewhere.

I've updated amino's time encoding to match with proto's behaviour (will push shortly).

- add tests against "google/protobuf/timestamp.proto
and clean up tests slightly
- add validation of seconds while encoding
- add error type InvalidTimeErr
- remove unnecessary var
- fix typo
- add changelog entry
-  ./codec.go:257:
PrintTypes passes lock by value: amino.Codec contains sync.RWMutex
- remove some unused (unexported) methods
@liamsi liamsi changed the title [WIP] proto3 compatibility: use varint encoding in time instead of fixed sized proto3 compatibility: use varint encoding in time instead of fixed sized Sep 8, 2018
@liamsi liamsi requested a review from ValarDragon September 8, 2018 15:09
@liamsi liamsi changed the title proto3 compatibility: use varint encoding in time instead of fixed sized proto3 compatibility: use uvarint encoding in time instead of fixed sized Sep 8, 2018
@liamsi liamsi changed the title proto3 compatibility: use uvarint encoding in time instead of fixed sized [WIP] proto3 compatibility: use uvarint encoding in time instead of fixed sized Sep 8, 2018
@liamsi liamsi changed the title [WIP] proto3 compatibility: use uvarint encoding in time instead of fixed sized proto3 compatibility: use uvarint encoding in time instead of fixed sized Sep 10, 2018
Copy link
Contributor

@ValarDragon ValarDragon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, just a few minor comments!

// seconds of 01-01-0001
minSeconds = -62135596800
// seconds of 10000-01-01
maxSeconds = 253402300800
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the standard upperbound? Just seems kinda weird since its not near a power of two. Doesn't block the PR though

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This constant is straight from the code that converts between time.Time and the wellknown type Timestamp: https://github.com/golang/protobuf/blob/ddf22928ea3c56eb4292a0adbbf5001b1e8e7d0d/ptypes/timestamp.go#L48-L50

decoder.go Outdated
@@ -261,15 +262,20 @@ func decodeNanos(bz *[]byte, n *int) (int32, error) {
if err != nil {
return 0, err
}
if fieldNum == 2 && typ == Typ3_4Byte {
if fieldNum == 2 && typ == Typ3_Varint {
slide(bz, n, _n)
_n = 0
// Actually read the Int32.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Outdated comment

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, good catch! Removed.

assert.Equal(t, p3.ProtoGotTime{T: nil}, pbRes)
}

func TestProto3CompatTimestampNow(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be table driven?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would be nice. But it's basically one test-case that documents what works how.

@liamsi liamsi merged commit 8171e3d into develop Oct 14, 2018
@liamsi
Copy link
Contributor Author

liamsi commented Oct 14, 2018

Merged! Thanks for the review @ValarDragon

// the original signed value:
res := int64(sec)
if res < minSeconds || res >= maxSeconds {
return 0, n, InvalidTimeErr(fmt.Sprintf("seconds have to be > %d and < %d, got: %d",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seconds have to be >= %d

if ns < 0 || ns > maxNanos {
// we could as well panic here:
// time.Time.Nanosecond() guarantees nanos to be in [0, 999,999,999]
return InvalidTimeErr(fmt.Sprintf("nanosecons have to be >= 0 and <= %v, got: %d",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nanoseconds

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I'll address this and above comment in #233

@liamsi liamsi deleted the its_time_again branch October 30, 2018 18:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants