Skip to content

Fix int/uint interoperation to conform to de-facto expectations of other clients #215

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

Merged
merged 4 commits into from
Jan 30, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions msgp/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,21 @@ func (u UintOverflow) Error() string {
// Resumable is always 'true' for overflows
func (u UintOverflow) Resumable() bool { return true }

// UintBelowZero is returned when a call
// would cast a signed integer below zero
// to an unsigned integer.
type UintBelowZero struct {
Value int64 // value of the incoming int
}

// Error implements the error interface
func (u UintBelowZero) Error() string {
return fmt.Sprintf("msgp: attempted to cast int %d to unsigned", u.Value)
}

// Resumable is always 'true' for overflows
func (u UintBelowZero) Resumable() bool { return true }

// A TypeError is returned when a particular
// decoding method is unsuitable for decoding
// a particular MessagePack value.
Expand Down
95 changes: 94 additions & 1 deletion msgp/read.go
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,14 @@ func (m *Reader) ReadInt64() (i int64, err error) {
i = int64(getMint8(p))
return

case muint8:
p, err = m.R.Next(2)
if err != nil {
return
}
i = int64(getMuint8(p))
return

case mint16:
p, err = m.R.Next(3)
if err != nil {
Expand All @@ -591,6 +599,14 @@ func (m *Reader) ReadInt64() (i int64, err error) {
i = int64(getMint16(p))
return

case muint16:
p, err = m.R.Next(3)
if err != nil {
return
}
i = int64(getMuint16(p))
return

case mint32:
p, err = m.R.Next(5)
if err != nil {
Expand All @@ -599,6 +615,14 @@ func (m *Reader) ReadInt64() (i int64, err error) {
i = int64(getMint32(p))
return

case muint32:
p, err = m.R.Next(5)
if err != nil {
return
}
i = int64(getMuint32(p))
return

case mint64:
p, err = m.R.Next(9)
if err != nil {
Expand All @@ -607,6 +631,19 @@ func (m *Reader) ReadInt64() (i int64, err error) {
i = getMint64(p)
return

case muint64:
p, err = m.R.Next(9)
if err != nil {
return
}
u := getMuint64(p)
if u > math.MaxInt64 {
err = UintOverflow{Value: u, FailedBitsize: 64}
return
}
i = int64(u)
return

default:
err = badPrefix(IntType, lead)
return
Expand Down Expand Up @@ -678,6 +715,19 @@ func (m *Reader) ReadUint64() (u uint64, err error) {
return
}
switch lead {
case mint8:
p, err = m.R.Next(2)
if err != nil {
return
}
v := int64(getMint8(p))
if v < 0 {
err = UintBelowZero{Value: v}
return
}
u = uint64(v)
return

case muint8:
p, err = m.R.Next(2)
if err != nil {
Expand All @@ -686,6 +736,19 @@ func (m *Reader) ReadUint64() (u uint64, err error) {
u = uint64(getMuint8(p))
return

case mint16:
p, err = m.R.Next(3)
if err != nil {
return
}
v := int64(getMint16(p))
if v < 0 {
err = UintBelowZero{Value: v}
return
}
u = uint64(v)
return

case muint16:
p, err = m.R.Next(3)
if err != nil {
Expand All @@ -694,6 +757,19 @@ func (m *Reader) ReadUint64() (u uint64, err error) {
u = uint64(getMuint16(p))
return

case mint32:
p, err = m.R.Next(5)
if err != nil {
return
}
v := int64(getMint32(p))
if v < 0 {
err = UintBelowZero{Value: v}
return
}
u = uint64(v)
return

case muint32:
p, err = m.R.Next(5)
if err != nil {
Expand All @@ -702,6 +778,19 @@ func (m *Reader) ReadUint64() (u uint64, err error) {
u = uint64(getMuint32(p))
return

case mint64:
p, err = m.R.Next(9)
if err != nil {
return
}
v := int64(getMint64(p))
if v < 0 {
err = UintBelowZero{Value: v}
return
}
u = uint64(v)
return

case muint64:
p, err = m.R.Next(9)
if err != nil {
Expand All @@ -711,7 +800,11 @@ func (m *Reader) ReadUint64() (u uint64, err error) {
return

default:
err = badPrefix(UintType, lead)
if isnfixint(lead) {
err = UintBelowZero{Value: int64(rnfixint(lead))}
} else {
err = badPrefix(UintType, lead)
}
return

}
Expand Down
105 changes: 103 additions & 2 deletions msgp/read_bytes.go
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,15 @@ func ReadInt64Bytes(b []byte) (i int64, o []byte, err error) {
o = b[2:]
return

case muint8:
if l < 2 {
err = ErrShortBytes
return
}
i = int64(getMuint8(b))
o = b[2:]
return

case mint16:
if l < 3 {
err = ErrShortBytes
Expand All @@ -377,6 +386,15 @@ func ReadInt64Bytes(b []byte) (i int64, o []byte, err error) {
o = b[3:]
return

case muint16:
if l < 3 {
err = ErrShortBytes
return
}
i = int64(getMuint16(b))
o = b[3:]
return

case mint32:
if l < 5 {
err = ErrShortBytes
Expand All @@ -386,12 +404,35 @@ func ReadInt64Bytes(b []byte) (i int64, o []byte, err error) {
o = b[5:]
return

case muint32:
if l < 5 {
err = ErrShortBytes
return
}
i = int64(getMuint32(b))
o = b[5:]
return

case mint64:
if l < 9 {
err = ErrShortBytes
return
}
i = getMint64(b)
i = int64(getMint64(b))
o = b[9:]
return

case muint64:
if l < 9 {
err = ErrShortBytes
return
}
u := getMuint64(b)
if u > math.MaxInt64 {
err = UintOverflow{Value: u, FailedBitsize: 64}
return
}
i = int64(u)
o = b[9:]
return

Expand Down Expand Up @@ -477,6 +518,20 @@ func ReadUint64Bytes(b []byte) (u uint64, o []byte, err error) {
}

switch lead {
case mint8:
if l < 2 {
err = ErrShortBytes
return
}
v := int64(getMint8(b))
if v < 0 {
err = UintBelowZero{Value: v}
return
}
u = uint64(v)
o = b[2:]
return

case muint8:
if l < 2 {
err = ErrShortBytes
Expand All @@ -486,6 +541,20 @@ func ReadUint64Bytes(b []byte) (u uint64, o []byte, err error) {
o = b[2:]
return

case mint16:
if l < 3 {
err = ErrShortBytes
return
}
v := int64(getMint16(b))
if v < 0 {
err = UintBelowZero{Value: v}
return
}
u = uint64(v)
o = b[3:]
return

case muint16:
if l < 3 {
err = ErrShortBytes
Expand All @@ -495,6 +564,20 @@ func ReadUint64Bytes(b []byte) (u uint64, o []byte, err error) {
o = b[3:]
return

case mint32:
if l < 5 {
err = ErrShortBytes
return
}
v := int64(getMint32(b))
if v < 0 {
err = UintBelowZero{Value: v}
return
}
u = uint64(v)
o = b[5:]
return

case muint32:
if l < 5 {
err = ErrShortBytes
Expand All @@ -504,6 +587,20 @@ func ReadUint64Bytes(b []byte) (u uint64, o []byte, err error) {
o = b[5:]
return

case mint64:
if l < 9 {
err = ErrShortBytes
return
}
v := int64(getMint64(b))
if v < 0 {
err = UintBelowZero{Value: v}
return
}
u = uint64(v)
o = b[9:]
return

case muint64:
if l < 9 {
err = ErrShortBytes
Expand All @@ -514,7 +611,11 @@ func ReadUint64Bytes(b []byte) (u uint64, o []byte, err error) {
return

default:
err = badPrefix(UintType, lead)
if isnfixint(lead) {
err = UintBelowZero{Value: int64(rnfixint(lead))}
} else {
err = badPrefix(UintType, lead)
}
return
}
}
Expand Down
Loading