Skip to content

Commit

Permalink
Fix issues reported by golangsci-lint
Browse files Browse the repository at this point in the history
  • Loading branch information
Danielius1922 committed Aug 22, 2024
1 parent 1285834 commit c4fa523
Show file tree
Hide file tree
Showing 14 changed files with 228 additions and 50 deletions.
16 changes: 9 additions & 7 deletions message/codes/codes.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"errors"
"fmt"
"strconv"

"github.com/plgd-dev/go-coap/v3/pkg/math"
)

// A Code is an unsigned 16-bit coap code as defined in the coap spec.
Expand Down Expand Up @@ -94,14 +96,15 @@ var strToCode = map[string]Code{
}

func getMaxCodeLen() int {
// max uint32 as string binary representation: "0b" + 32 digits
max := 34
// maxLen uint32 as string binary representation: "0b" + 32 digits
maxLen := 34
for k := range strToCode {
if len(k) > max {
max = len(k)
kLen := len(k)
if kLen > maxLen {
maxLen = kLen
}
}
return max
return maxLen
}

func init() {
Expand All @@ -128,8 +131,7 @@ func (c *Code) UnmarshalJSON(b []byte) error {
if ci >= _maxCode {
return fmt.Errorf("invalid code: %q", ci)
}

*c = Code(ci)
*c = math.CastTo[Code](ci)
return nil
}

Expand Down
4 changes: 3 additions & 1 deletion message/encodeDecodeUint32.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package message

import (
"encoding/binary"

"github.com/plgd-dev/go-coap/v3/pkg/math"
)

func EncodeUint32(buf []byte, value uint32) (int, error) {
Expand All @@ -18,7 +20,7 @@ func EncodeUint32(buf []byte, value uint32) (int, error) {
if len(buf) < 2 {
return 2, ErrTooSmall
}
binary.BigEndian.PutUint16(buf, uint16(value))
binary.BigEndian.PutUint16(buf, math.CastTo[uint16](value))
return 2, nil
case value <= max3ByteNumber:
if len(buf) < 3 {
Expand Down
7 changes: 4 additions & 3 deletions message/getmid.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"sync/atomic"
"time"

pkgMath "github.com/plgd-dev/go-coap/v3/pkg/math"
pkgRand "github.com/plgd-dev/go-coap/v3/pkg/rand"
)

Expand All @@ -16,17 +17,17 @@ var msgID = uint32(RandMID())

// GetMID generates a message id for UDP. (0 <= mid <= 65535)
func GetMID() int32 {
return int32(uint16(atomic.AddUint32(&msgID, 1)))
return int32(pkgMath.CastTo[uint16](atomic.AddUint32(&msgID, 1)))
}

func RandMID() int32 {
b := make([]byte, 4)
_, err := rand.Read(b)
if err != nil {
// fallback to cryptographically insecure pseudo-random generator
return int32(uint16(weakRng.Uint32() >> 16))
return int32(pkgMath.CastTo[uint16](weakRng.Uint32() >> 16))
}
return int32(uint16(binary.BigEndian.Uint32(b)))
return int32(pkgMath.CastTo[uint16](binary.BigEndian.Uint32(b)))
}

// ValidateMID validates a message id for UDP. (0 <= mid <= 65535)
Expand Down
20 changes: 18 additions & 2 deletions message/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import (
"encoding/binary"
"errors"
"strconv"

"github.com/plgd-dev/go-coap/v3/pkg/math"
"golang.org/x/exp/constraints"
)

const (
Expand Down Expand Up @@ -236,6 +239,18 @@ func ToMediaType(v string) (MediaType, error) {
return 0, errors.New("not found")
}

func MediaTypeFromNumber[T constraints.Integer](v T) (MediaType, error) {
mt, err := math.SafeCastTo[MediaType](v)
if err != nil {
return MediaType(0), err
}
_, ok := mediaTypeToString[mt]
if !ok {
return MediaType(0), errors.New("invalid value")
}
return mt, nil
}

func extendOpt(opt int) (int, int) {
ext := 0
if opt >= ExtendOptionByteAddend {
Expand Down Expand Up @@ -269,7 +284,7 @@ func marshalOptionHeaderExt(buf []byte, opt, ext int) (int, error) {
return 1, ErrTooSmall
case ExtendOptionWordCode:
if len(buf) > 1 {
binary.BigEndian.PutUint16(buf, uint16(ext))
binary.BigEndian.PutUint16(buf, math.CastTo[uint16](ext))
return 2, nil
}
return 2, ErrTooSmall
Expand Down Expand Up @@ -435,7 +450,8 @@ func (o *Option) Unmarshal(data []byte, optionDefs map[OptionID]OptionDef, optio
// Skip unrecognized options (RFC7252 section 5.4.1)
return len(data), nil
}
if uint32(len(data)) < def.MinLen || uint32(len(data)) > def.MaxLen {
dataLen := math.CastTo[uint32](len(data))
if dataLen < def.MinLen || dataLen > def.MaxLen {
// Skip options with illegal value length (RFC7252 section 5.4.3)
return len(data), nil
}
Expand Down
18 changes: 15 additions & 3 deletions message/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ package message

import (
"errors"
"fmt"
"strings"

"github.com/plgd-dev/go-coap/v3/pkg/math"
)

// Options Container of COAP Options, It must be always sort'ed after modification.
Expand Down Expand Up @@ -207,7 +210,10 @@ func (options Options) GetUint32(id OptionID) (uint32, error) {
// ContentFormat gets the content format of body.
func (options Options) ContentFormat() (MediaType, error) {
v, err := options.GetUint32(ContentFormat)
return MediaType(v), err
if err != nil {
return MediaType(0), err
}
return MediaTypeFromNumber(v)
}

// GetString gets the string value of the first option with the given ID.
Expand Down Expand Up @@ -353,7 +359,10 @@ func (options Options) SetAccept(buf []byte, contentFormat MediaType) (Options,
// Accept gets accept option.
func (options Options) Accept() (MediaType, error) {
v, err := options.GetUint32(Accept)
return MediaType(v), err
if err != nil {
return MediaType(0), err
}
return MediaTypeFromNumber(v)
}

// Find returns range of type options. First number is index and second number is index of next option type.
Expand Down Expand Up @@ -576,7 +585,10 @@ func (options *Options) Unmarshal(data []byte, optionDefs map[OptionID]OptionDef
}

option := Option{}
oid := OptionID(prev + delta)
oid, err := math.SafeCastTo[OptionID](prev + delta)
if err != nil {
return -1, fmt.Errorf("%w: %w", ErrOptionNotFound, err)
}
proc, err = option.Unmarshal(data[:length], optionDefs, oid)
if err != nil {
return -1, err
Expand Down
10 changes: 8 additions & 2 deletions message/pool/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,10 @@ func (r *Message) AddOptionUint32(opt message.OptionID, value uint32) {

func (r *Message) ContentFormat() (message.MediaType, error) {
v, err := r.GetOptionUint32(message.ContentFormat)
return message.MediaType(v), err
if err != nil {
return message.MediaType(0), err
}
return message.MediaTypeFromNumber(v)
}

func (r *Message) HasOption(id message.OptionID) bool {
Expand All @@ -400,7 +403,10 @@ func (r *Message) SetAccept(contentFormat message.MediaType) {
// Accept get's accept option.
func (r *Message) Accept() (message.MediaType, error) {
v, err := r.GetOptionUint32(message.Accept)
return message.MediaType(v), err
if err != nil {
return message.MediaType(0), err
}
return message.MediaTypeFromNumber(v)
}

func (r *Message) BodySize() (int64, error) {
Expand Down
23 changes: 16 additions & 7 deletions net/blockwise/blockwise.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/plgd-dev/go-coap/v3/message/pool"
"github.com/plgd-dev/go-coap/v3/net/responsewriter"
"github.com/plgd-dev/go-coap/v3/pkg/cache"
"github.com/plgd-dev/go-coap/v3/pkg/math"
"golang.org/x/sync/semaphore"
)

Expand Down Expand Up @@ -98,13 +99,13 @@ func EncodeBlockOption(szx SZX, blockNumber int64, moreBlocksFollowing bool) (ui
if blockNumber > maxBlockNumber {
return 0, ErrBlockNumberExceedLimit
}
blockVal := uint32(blockNumber << 4)
blockVal := math.CastTo[uint32](blockNumber << 4)
m := uint32(0)
if moreBlocksFollowing {
m = 1
}
blockVal += m << 3
blockVal += uint32(szx)
blockVal += math.CastTo[uint32](szx)
return blockVal, nil
}

Expand Down Expand Up @@ -238,7 +239,11 @@ func (b *BlockWise[C]) Do(r *pool.Message, maxSzx SZX, maxMessageSize uint32, do
}
req := b.cloneMessage(r)
defer b.cc.ReleaseMessage(req)
req.SetOptionUint32(message.Size1, uint32(payloadSize))
payloadSizeUint32, err := math.SafeCastTo[uint32](payloadSize)
if err != nil {
return nil, fmt.Errorf("cannot set payload size: %w", err)
}
req.SetOptionUint32(message.Size1, payloadSizeUint32)
block, err := EncodeBlockOption(maxSzx, 0, true)
if err != nil {
return nil, fmt.Errorf("cannot encode block option(%v, %v, %v) to bw request: %w", maxSzx, 0, true, err)
Expand Down Expand Up @@ -436,9 +441,7 @@ func (b *BlockWise[C]) createSendingMessage(sendingMessage *pool.Message, maxSZX
b.cc.ReleaseMessage(sendMessage)
return nil, false, payloadSizeError(err)
}
if szx > maxSZX {
szx = maxSZX
}
szx = getSzx(szx, maxSZX)
newBufLen := bufferSize(szx, maxMessageSize)
off := num * szx.Size()
if blockType == message.Block1 {
Expand Down Expand Up @@ -471,13 +474,19 @@ func (b *BlockWise[C]) createSendingMessage(sendingMessage *pool.Message, maxSZX
return nil, false, fmt.Errorf("cannot read response: %w", err)
}

payloadSizeUint32, err := math.SafeCastTo[uint32](payloadSize)
if err != nil {
b.cc.ReleaseMessage(sendMessage)
return nil, false, fmt.Errorf("cannot set payload size: %w", err)
}
sendMessage.SetOptionUint32(sizeType, payloadSizeUint32)

buf = buf[:readed]
sendMessage.SetBody(bytes.NewReader(buf))
more = true
if offSeek+int64(readed) == payloadSize {
more = false
}
sendMessage.SetOptionUint32(sizeType, uint32(payloadSize))
num = (offSeek) / szx.Size()
block, err = EncodeBlockOption(szx, num, more)
if err != nil {
Expand Down
56 changes: 56 additions & 0 deletions pkg/math/cast.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package math

import (
"fmt"
"log"
"reflect"
"unsafe"

"golang.org/x/exp/constraints"
)

func Max[T constraints.Integer]() T {
size := unsafe.Sizeof(T(0))
switch reflect.TypeFor[T]().Kind() {

Check failure on line 14 in pkg/math/cast.go

View workflow job for this annotation

GitHub Actions / test1_20

undefined: reflect.TypeFor
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return T(1<<(size*8-1) - 1) // 2^(n-1) - 1 for signed integers
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return T(1<<(size*8) - 1) // 2^n - 1 for unsigned integers
default:
panic("unsupported type")
}
}

func Min[T constraints.Integer]() T {
size := unsafe.Sizeof(T(0))
switch reflect.TypeFor[T]().Kind() {

Check failure on line 26 in pkg/math/cast.go

View workflow job for this annotation

GitHub Actions / test1_20

undefined: reflect.TypeFor
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return T(int64(-1) << (size*8 - 1)) // -2^(n-1)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return T(0)
default:
panic("unsupported type")
}
}

func SafeCastTo[T, F constraints.Integer](from F) (T, error) {
if from > 0 && uint64(Max[T]()) < uint64(from) {
return T(0), fmt.Errorf("value(%v) exceeds the maximum value for type(%v)", from, Max[T]())
}
if from < 0 && int64(Min[T]()) > int64(from) {
return T(0), fmt.Errorf("value(%v) exceeds the minimum value for type(%v)", from, Min[T]())
}
return T(from), nil
}

func CastTo[T, F constraints.Integer](from F) T {
return T(from)
}

func MustSafeCastTo[T, F constraints.Integer](from F) T {
to, err := SafeCastTo[T](from)
if err != nil {
log.Panicf("value (%v) out of bounds for type %T", from, T(0))
}
return to
}
Loading

0 comments on commit c4fa523

Please sign in to comment.