Skip to content
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

Fix prepared statement buffer overwriting bug #5562

Merged
merged 1 commit into from
Dec 13, 2019
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
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ require (
github.com/golang/mock v1.3.1
github.com/golang/protobuf v1.3.2
github.com/golang/snappy v0.0.0-20170215233205-553a64147049
github.com/google/btree v1.0.0 // indirect
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf // indirect
github.com/gorilla/websocket v0.0.0-20160912153041-2d1e4548da23
github.com/grpc-ecosystem/go-grpc-middleware v1.1.0
Expand All @@ -49,6 +50,8 @@ require (
github.com/minio/minio-go v0.0.0-20190131015406-c8a261de75c1
github.com/mitchellh/go-testing-interface v1.0.0 // indirect
github.com/mitchellh/mapstructure v1.1.2 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.1 // indirect
github.com/olekukonko/tablewriter v0.0.0-20160115111002-cca8bbc07984
github.com/opentracing-contrib/go-grpc v0.0.0-20180928155321-4b5a12d3ff02
github.com/opentracing/opentracing-go v1.1.0
Expand Down
14 changes: 14 additions & 0 deletions go/mysql/encoding.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,3 +281,17 @@ func readLenEncStringAsBytes(data []byte, pos int) ([]byte, int, bool) {
}
return data[pos : pos+s], pos + s, true
}

func readLenEncStringAsBytesCopy(data []byte, pos int) ([]byte, int, bool) {
size, pos, ok := readLenEncInt(data, pos)
if !ok {
return nil, 0, false
}
s := int(size)
if pos+s-1 >= len(data) {
return nil, 0, false
}
result := make([]byte, size)
copy(result, data[pos:pos+s])
return result, pos + s, true
}
18 changes: 18 additions & 0 deletions go/mysql/encoding_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,24 @@ func TestEncString(t *testing.T) {
t.Errorf("readLenEncStringAsBytes returned ok=true for empty value %v", test.value)
}

// Check successful decoding as bytes.
gotbcopy, posCopy, ok := readLenEncStringAsBytesCopy(test.lenEncoded, 0)
if !ok || string(gotb) != test.value || pos != len(test.lenEncoded) {
t.Errorf("readLenEncString returned %v/%v/%v but expected %v/%v/%v", gotbcopy, posCopy, ok, test.value, len(test.lenEncoded), true)
}

// Check failed decoding as bytes with shorter data.
_, _, ok = readLenEncStringAsBytesCopy(test.lenEncoded[:len(test.lenEncoded)-1], 0)
if ok {
t.Errorf("readLenEncStringAsBytes returned ok=true for shorter value %v", test.value)
}

// Check failed decoding as bytes with no data.
_, _, ok = readLenEncStringAsBytesCopy([]byte{}, 0)
if ok {
t.Errorf("readLenEncStringAsBytes returned ok=true for empty value %v", test.value)
}

// null encoded tests.

// Check successful encoding.
Expand Down
4 changes: 2 additions & 2 deletions go/mysql/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ func (c *Conn) parseRow(data []byte, fields []*querypb.Field) ([]sqltypes.Value,
}
var s []byte
var ok bool
s, pos, ok = readLenEncStringAsBytes(data, pos)
s, pos, ok = readLenEncStringAsBytesCopy(data, pos)
if !ok {
return nil, NewSQLError(CRMalformedPacket, SSUnknownSQLState, "decoding string failed")
}
Expand Down Expand Up @@ -823,7 +823,7 @@ func (c *Conn) parseStmtArgs(data []byte, typ querypb.Type, pos int) (sqltypes.V
}
case sqltypes.Decimal, sqltypes.Text, sqltypes.Blob, sqltypes.VarChar, sqltypes.VarBinary, sqltypes.Char,
sqltypes.Bit, sqltypes.Enum, sqltypes.Set, sqltypes.Geometry, sqltypes.Binary, sqltypes.TypeJSON:
val, pos, ok := readLenEncStringAsBytes(data, pos)
val, pos, ok := readLenEncStringAsBytesCopy(data, pos)
return sqltypes.MakeTrusted(sqltypes.VarBinary, val), pos, ok
default:
return sqltypes.NULL, pos, false
Expand Down