Skip to content

Commit ef1dd3b

Browse files
committed
bugfix: Invalid MsgPack if STREAM_ID > 127
The patch fixes an error if a stream id value > 127: Invalid MsgPack - packet header (0x14) Closes #223
1 parent a156f4e commit ef1dd3b

File tree

3 files changed

+58
-7
lines changed

3 files changed

+58
-7
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ Versioning](http://semver.org/spec/v2.0.0.html) except to the first release.
3636
package-level function getNumberLength (#219)
3737
- Datetime location after encode + decode is unequal (#217)
3838
- Wrong interval arithmetic with timezones (#221)
39+
- Invalid MsgPack if STREAM_ID > 127 (#224)
3940

4041
## [1.8.0] - 2022-08-17
4142

connection.go

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ import (
66
"bufio"
77
"bytes"
88
"context"
9+
"encoding/binary"
910
"errors"
1011
"fmt"
1112
"io"
1213
"log"
14+
"math"
1315
"net"
1416
"runtime"
1517
"sync"
@@ -531,23 +533,38 @@ func (conn *Connection) dial() (err error) {
531533

532534
func pack(h *smallWBuf, enc *encoder, reqid uint32,
533535
req Request, streamId uint64, res SchemaResolver) (err error) {
536+
const uint32Code = 0xce
537+
const uint64Code = 0xcf
538+
const streamBytesLenUint64 = 10
539+
const streamBytesLenUint32 = 6
540+
534541
hl := h.Len()
535542

543+
var streamBytesLen = 0
544+
var streamBytes [streamBytesLenUint64]byte
536545
hMapLen := byte(0x82) // 2 element map.
537546
if streamId != ignoreStreamId {
538547
hMapLen = byte(0x83) // 3 element map.
548+
streamBytes[0] = KeyStreamId
549+
if streamId > math.MaxUint32 {
550+
streamBytesLen = streamBytesLenUint64
551+
streamBytes[1] = uint64Code
552+
binary.BigEndian.PutUint64(streamBytes[2:], streamId)
553+
} else {
554+
streamBytesLen = streamBytesLenUint32
555+
streamBytes[1] = uint32Code
556+
binary.BigEndian.PutUint32(streamBytes[2:], uint32(streamId))
557+
}
539558
}
540-
hBytes := []byte{
541-
0xce, 0, 0, 0, 0, // Length.
559+
560+
hBytes := append([]byte{
561+
uint32Code, 0, 0, 0, 0, // Length.
542562
hMapLen,
543563
KeyCode, byte(req.Code()), // Request code.
544-
KeySync, 0xce,
564+
KeySync, uint32Code,
545565
byte(reqid >> 24), byte(reqid >> 16),
546566
byte(reqid >> 8), byte(reqid),
547-
}
548-
if streamId != ignoreStreamId {
549-
hBytes = append(hBytes, KeyStreamId, byte(streamId))
550-
}
567+
}, streamBytes[:streamBytesLen]...)
551568

552569
h.Write(hBytes)
553570

tarantool_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"fmt"
66
"log"
7+
"math"
78
"os"
89
"reflect"
910
"runtime"
@@ -2442,6 +2443,38 @@ func TestComplexStructs(t *testing.T) {
24422443
}
24432444
}
24442445

2446+
func TestStream_IdValues(t *testing.T) {
2447+
test_helpers.SkipIfStreamsUnsupported(t)
2448+
2449+
conn := test_helpers.ConnectWithValidation(t, server, opts)
2450+
defer conn.Close()
2451+
2452+
cases := []uint64{
2453+
1,
2454+
128,
2455+
math.MaxUint8,
2456+
math.MaxUint8 + 1,
2457+
math.MaxUint16,
2458+
math.MaxUint16 + 1,
2459+
math.MaxUint32,
2460+
math.MaxUint32 + 1,
2461+
math.MaxUint64,
2462+
}
2463+
2464+
stream, _ := conn.NewStream()
2465+
req := NewPingRequest()
2466+
2467+
for _, id := range cases {
2468+
t.Run(fmt.Sprintf("%d", id), func(t *testing.T) {
2469+
stream.Id = id
2470+
_, err := stream.Do(req).Get()
2471+
if err != nil {
2472+
t.Fatalf("Failed to Ping: %s", err.Error())
2473+
}
2474+
})
2475+
}
2476+
}
2477+
24452478
func TestStream_Commit(t *testing.T) {
24462479
var req Request
24472480
var resp *Response

0 commit comments

Comments
 (0)