Skip to content

Commit ec789f2

Browse files
jkralikvitprajzler
andauthored
Fix off-by-one error in upserts (#423)
* Fix off-by-one error in upserts There are two off-by-one errors in the upsert functions for message ID and message type. UpsertMessageId should allow a value of 65535, while UpsertType should allow 255. Without this fix, a device sending a confirmable message to the server will receive an ACK message back with an incorrect Message ID. Co-authored-by: Vit Prajzler <28387418+vitprajzler@users.noreply.github.com>
1 parent ac1d638 commit ec789f2

File tree

6 files changed

+42
-11
lines changed

6 files changed

+42
-11
lines changed

message/getmid.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package message
33
import (
44
"crypto/rand"
55
"encoding/binary"
6+
"math"
67
mathRand "math/rand"
78
"sync/atomic"
89
"time"
@@ -14,7 +15,7 @@ func init() {
1415

1516
var msgID = uint32(RandMID())
1617

17-
// GetMID generates a message id for UDP-coap
18+
// GetMID generates a message id for UDP. (0 <= mid <= 65535)
1819
func GetMID() int32 {
1920
return int32(uint16(atomic.AddUint32(&msgID, 1)))
2021
}
@@ -28,3 +29,8 @@ func RandMID() int32 {
2829
}
2930
return int32(uint16(binary.BigEndian.Uint32(b)))
3031
}
32+
33+
// ValidateMID validates a message id for UDP. (0 <= mid <= 65535)
34+
func ValidateMID(mid int32) bool {
35+
return mid >= 0 && mid <= math.MaxUint16
36+
}

message/message.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package message
22

33
import (
44
"fmt"
5-
"math"
65

76
"github.com/plgd-dev/go-coap/v3/message/codes"
87
)
@@ -38,10 +37,10 @@ func (r *Message) String() string {
3837
if err == nil {
3938
buf = fmt.Sprintf("%s, Queries: %+v", buf, queries)
4039
}
41-
if r.Type >= 0 && r.Type < math.MaxUint8 {
40+
if ValidateType(r.Type) {
4241
buf = fmt.Sprintf("%s, Type: %v", buf, r.Type)
4342
}
44-
if r.MessageID >= 0 && r.MessageID < math.MaxUint16 {
43+
if ValidateMID(r.MessageID) {
4544
buf = fmt.Sprintf("%s, MessageID: %v", buf, r.MessageID)
4645
}
4746
if len(r.Payload) > 0 {

message/pool/message.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"errors"
77
"fmt"
88
"io"
9-
"math"
109

1110
"github.com/plgd-dev/go-coap/v3/message"
1211
"github.com/plgd-dev/go-coap/v3/message/codes"
@@ -81,7 +80,7 @@ func (r *Message) SetMessageID(mid int32) {
8180

8281
// UpsertMessageID set value only when origin value is invalid. Only 0 to 2^16-1 values are valid.
8382
func (r *Message) UpsertMessageID(mid int32) {
84-
if r.msg.MessageID >= 0 && r.msg.MessageID < math.MaxUint16 {
83+
if message.ValidateMID(r.msg.MessageID) {
8584
return
8685
}
8786
r.SetMessageID(mid)
@@ -99,7 +98,7 @@ func (r *Message) SetType(typ message.Type) {
9998

10099
// UpsertType set value only when origin value is invalid. Only 0 to 2^8-1 values are valid.
101100
func (r *Message) UpsertType(typ message.Type) {
102-
if r.msg.Type >= 0 && r.msg.Type < math.MaxUint8 {
101+
if message.ValidateType(r.msg.Type) {
103102
return
104103
}
105104
r.SetType(typ)

message/type.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package message
22

33
import (
4+
"math"
45
"strconv"
56
)
67

@@ -37,3 +38,8 @@ func (t Type) String() string {
3738
}
3839
return "Type(" + strconv.FormatInt(int64(t), 10) + ")"
3940
}
41+
42+
// ValidateType validates the type for UDP. (0 <= typ <= 255)
43+
func ValidateType(typ Type) bool {
44+
return typ >= 0 && typ <= math.MaxUint8
45+
}

udp/coder/coder.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"encoding/binary"
55
"errors"
66
"fmt"
7-
"math"
87

98
"github.com/plgd-dev/go-coap/v3/message"
109
"github.com/plgd-dev/go-coap/v3/message/codes"
@@ -46,10 +45,10 @@ func (c *Coder) Encode(m message.Message, buf []byte) (int, error) {
4645
|1 1 1 1 1 1 1 1| Payload (if any) ...
4746
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4847
*/
49-
if m.MessageID < 0 || m.MessageID > math.MaxUint16 {
48+
if !message.ValidateMID(m.MessageID) {
5049
return -1, fmt.Errorf("invalid MessageID(%v)", m.MessageID)
5150
}
52-
if m.Type < 0 || m.Type > math.MaxUint8 {
51+
if !message.ValidateType(m.Type) {
5352
return -1, fmt.Errorf("invalid Type(%v)", m.Type)
5453
}
5554
size, err := c.Size(m)

udp/coder/coder_test.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package coder
22

33
import (
4+
"math"
45
"testing"
56

67
"github.com/plgd-dev/go-coap/v3/message"
@@ -24,6 +25,27 @@ func testUnmarshalMessage(t *testing.T, msg message.Message, buf []byte, expecte
2425

2526
func TestMarshalMessage(t *testing.T) {
2627
buf := make([]byte, 1024)
28+
29+
// validate messageID
30+
_, err := DefaultCoder.Encode(message.Message{MessageID: 0}, buf)
31+
require.NoError(t, err)
32+
_, err = DefaultCoder.Encode(message.Message{MessageID: -1}, buf)
33+
require.Error(t, err)
34+
_, err = DefaultCoder.Encode(message.Message{MessageID: math.MaxUint16}, buf)
35+
require.NoError(t, err)
36+
_, err = DefaultCoder.Encode(message.Message{MessageID: math.MaxUint16 + 1}, buf)
37+
require.Error(t, err)
38+
39+
// validate type
40+
_, err = DefaultCoder.Encode(message.Message{Type: 0}, buf)
41+
require.NoError(t, err)
42+
_, err = DefaultCoder.Encode(message.Message{Type: -1}, buf)
43+
require.Error(t, err)
44+
_, err = DefaultCoder.Encode(message.Message{Type: math.MaxUint8}, buf)
45+
require.NoError(t, err)
46+
_, err = DefaultCoder.Encode(message.Message{Type: math.MaxUint8 + 1}, buf)
47+
require.Error(t, err)
48+
2749
testMarshalMessage(t, message.Message{}, buf, []byte{64, 0, 0, 0})
2850
testMarshalMessage(t, message.Message{Code: codes.GET}, buf, []byte{64, byte(codes.GET), 0, 0})
2951
testMarshalMessage(t, message.Message{Code: codes.GET, Payload: []byte{0x1}}, buf, []byte{64, byte(codes.GET), 0, 0, 0xff, 0x1})
@@ -57,7 +79,7 @@ func TestMarshalMessage(t *testing.T) {
5779
bufOptionsUsed := bufOptions
5880
options := make(message.Options, 0, 32)
5981
enc := 0
60-
options, enc, err := options.SetPath(bufOptionsUsed, "/a/b/c/d/e")
82+
options, enc, err = options.SetPath(bufOptionsUsed, "/a/b/c/d/e")
6183
if err != nil {
6284
t.Fatalf("Cannot set uri")
6385
}

0 commit comments

Comments
 (0)