Skip to content

Commit

Permalink
GODRIVER-3240 Replace bit-shifting; apply size check for integer conv…
Browse files Browse the repository at this point in the history
…ersions.
  • Loading branch information
qingyang-hu committed Jun 25, 2024
1 parent fb39da8 commit 26a05fc
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 29 deletions.
4 changes: 2 additions & 2 deletions bson/bsoncodec/default_value_decoders.go
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ func (DefaultValueDecoders) intDecodeType(dc DecodeContext, vr bsonrw.ValueReade
case reflect.Int64:
return reflect.ValueOf(i64), nil
case reflect.Int:
if int64(int(i64)) != i64 { // Can we fit this inside of an int
if i64 > math.MaxInt { // Can we fit this inside of an int
return emptyValue, fmt.Errorf("%d overflows int", i64)
}

Expand Down Expand Up @@ -434,7 +434,7 @@ func (dvd DefaultValueDecoders) UintDecodeValue(dc DecodeContext, vr bsonrw.Valu
return fmt.Errorf("%d overflows uint64", i64)
}
case reflect.Uint:
if i64 < 0 || int64(uint(i64)) != i64 { // Can we fit this inside of an uint
if i64 < 0 || uint64(i64) > uint64(math.MaxUint) { // Can we fit this inside of an uint
return fmt.Errorf("%d overflows uint", i64)
}
default:
Expand Down
2 changes: 1 addition & 1 deletion bson/bsoncodec/uint_codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ func (uic *UIntCodec) decodeType(dc DecodeContext, vr bsonrw.ValueReader, t refl

return reflect.ValueOf(uint64(i64)), nil
case reflect.Uint:
if i64 < 0 || int64(uint(i64)) != i64 { // Can we fit this inside of an uint
if i64 < 0 || uint64(i64) > uint64(math.MaxUint) { // Can we fit this inside of an uint
return emptyValue, fmt.Errorf("%d overflows uint", i64)
}

Expand Down
7 changes: 5 additions & 2 deletions bson/bsonrw/extjson_wrappers.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package bsonrw

import (
"encoding/base64"
"encoding/binary"
"errors"
"fmt"
"math"
Expand Down Expand Up @@ -95,12 +96,14 @@ func (ejv *extJSONValue) parseBinary() (b []byte, subType byte, err error) {
return nil, 0, fmt.Errorf("$binary subType value should be string, but instead is %s", val.t)
}

i, err := strconv.ParseInt(val.v.(string), 16, 64)
i, err := strconv.ParseUint(val.v.(string), 16, 64)
if err != nil {
return nil, 0, fmt.Errorf("invalid $binary subType string: %s", val.v.(string))
}

subType = byte(i)
b := []byte{0, 0, 0, 0, 0, 0, 0, 0}
binary.LittleEndian.PutUint64(b, i)
subType = b[0]
stFound = true
default:
return nil, 0, fmt.Errorf("invalid key in $binary object: %s", key)
Expand Down
12 changes: 5 additions & 7 deletions bson/bsonrw/value_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -842,7 +842,7 @@ func (vr *valueReader) peekLength() (int32, error) {
}

idx := vr.offset
return (int32(vr.d[idx]) | int32(vr.d[idx+1])<<8 | int32(vr.d[idx+2])<<16 | int32(vr.d[idx+3])<<24), nil
return int32(binary.LittleEndian.Uint32(vr.d[idx:])), nil
}

func (vr *valueReader) readLength() (int32, error) { return vr.readi32() }
Expand All @@ -854,7 +854,7 @@ func (vr *valueReader) readi32() (int32, error) {

idx := vr.offset
vr.offset += 4
return (int32(vr.d[idx]) | int32(vr.d[idx+1])<<8 | int32(vr.d[idx+2])<<16 | int32(vr.d[idx+3])<<24), nil
return int32(binary.LittleEndian.Uint32(vr.d[idx:])), nil
}

func (vr *valueReader) readu32() (uint32, error) {
Expand All @@ -864,7 +864,7 @@ func (vr *valueReader) readu32() (uint32, error) {

idx := vr.offset
vr.offset += 4
return (uint32(vr.d[idx]) | uint32(vr.d[idx+1])<<8 | uint32(vr.d[idx+2])<<16 | uint32(vr.d[idx+3])<<24), nil
return binary.LittleEndian.Uint32(vr.d[idx:]), nil
}

func (vr *valueReader) readi64() (int64, error) {
Expand All @@ -874,8 +874,7 @@ func (vr *valueReader) readi64() (int64, error) {

idx := vr.offset
vr.offset += 8
return int64(vr.d[idx]) | int64(vr.d[idx+1])<<8 | int64(vr.d[idx+2])<<16 | int64(vr.d[idx+3])<<24 |
int64(vr.d[idx+4])<<32 | int64(vr.d[idx+5])<<40 | int64(vr.d[idx+6])<<48 | int64(vr.d[idx+7])<<56, nil
return int64(binary.LittleEndian.Uint64(vr.d[idx:])), nil
}

func (vr *valueReader) readu64() (uint64, error) {
Expand All @@ -885,6 +884,5 @@ func (vr *valueReader) readu64() (uint64, error) {

idx := vr.offset
vr.offset += 8
return uint64(vr.d[idx]) | uint64(vr.d[idx+1])<<8 | uint64(vr.d[idx+2])<<16 | uint64(vr.d[idx+3])<<24 |
uint64(vr.d[idx+4])<<32 | uint64(vr.d[idx+5])<<40 | uint64(vr.d[idx+6])<<48 | uint64(vr.d[idx+7])<<56, nil
return binary.LittleEndian.Uint64(vr.d[idx:]), nil
}
31 changes: 14 additions & 17 deletions x/bsonx/bsoncore/bsoncore.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package bsoncore // import "go.mongodb.org/mongo-driver/x/bsonx/bsoncore"

import (
"bytes"
"encoding/binary"
"fmt"
"math"
"strconv"
Expand Down Expand Up @@ -734,51 +735,47 @@ func readi32(src []byte) (int32, []byte, bool) {
if len(src) < 4 {
return 0, src, false
}
return (int32(src[0]) | int32(src[1])<<8 | int32(src[2])<<16 | int32(src[3])<<24), src[4:], true
return int32(binary.LittleEndian.Uint32(src)), src[4:], true
}

func appendi64(dst []byte, i64 int64) []byte {
return append(dst,
byte(i64), byte(i64>>8), byte(i64>>16), byte(i64>>24),
byte(i64>>32), byte(i64>>40), byte(i64>>48), byte(i64>>56),
)
b := []byte{0, 0, 0, 0, 0, 0, 0, 0}
binary.LittleEndian.PutUint64(b, uint64(i64))
return append(dst, b...)
}

func readi64(src []byte) (int64, []byte, bool) {
if len(src) < 8 {
return 0, src, false
}
i64 := (int64(src[0]) | int64(src[1])<<8 | int64(src[2])<<16 | int64(src[3])<<24 |
int64(src[4])<<32 | int64(src[5])<<40 | int64(src[6])<<48 | int64(src[7])<<56)
return i64, src[8:], true
return int64(binary.LittleEndian.Uint64(src)), src[8:], true
}

func appendu32(dst []byte, u32 uint32) []byte {
return append(dst, byte(u32), byte(u32>>8), byte(u32>>16), byte(u32>>24))
b := []byte{0, 0, 0, 0}
binary.LittleEndian.PutUint32(b, u32)
return append(dst, b...)
}

func readu32(src []byte) (uint32, []byte, bool) {
if len(src) < 4 {
return 0, src, false
}

return (uint32(src[0]) | uint32(src[1])<<8 | uint32(src[2])<<16 | uint32(src[3])<<24), src[4:], true
return binary.LittleEndian.Uint32(src), src[4:], true
}

func appendu64(dst []byte, u64 uint64) []byte {
return append(dst,
byte(u64), byte(u64>>8), byte(u64>>16), byte(u64>>24),
byte(u64>>32), byte(u64>>40), byte(u64>>48), byte(u64>>56),
)
b := []byte{0, 0, 0, 0, 0, 0, 0, 0}
binary.LittleEndian.PutUint64(b, u64)
return append(dst, b...)
}

func readu64(src []byte) (uint64, []byte, bool) {
if len(src) < 8 {
return 0, src, false
}
u64 := (uint64(src[0]) | uint64(src[1])<<8 | uint64(src[2])<<16 | uint64(src[3])<<24 |
uint64(src[4])<<32 | uint64(src[5])<<40 | uint64(src[6])<<48 | uint64(src[7])<<56)
return u64, src[8:], true
return binary.LittleEndian.Uint64(src), src[8:], true
}

// keep in sync with readcstringbytes
Expand Down

0 comments on commit 26a05fc

Please sign in to comment.