Bump github.com/godbus/dbus/v5 from 5.0.4 to 5.0.5

Bumps [github.com/godbus/dbus/v5](https://github.com/godbus/dbus) from 5.0.4 to 5.0.5.
- [Release notes](https://github.com/godbus/dbus/releases)
- [Commits](https://github.com/godbus/dbus/compare/v5.0.4...v5.0.5)

---
updated-dependencies:
- dependency-name: github.com/godbus/dbus/v5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
dependabot[bot]
2021-09-09 16:16:56 +00:00
committed by GitHub
parent 784e1ae137
commit c65b43a0fa
13 changed files with 234 additions and 99 deletions

2
go.mod
View File

@ -32,7 +32,7 @@ require (
github.com/dtylman/scp v0.0.0-20181017070807-f3000a34aef4 github.com/dtylman/scp v0.0.0-20181017070807-f3000a34aef4
github.com/fsnotify/fsnotify v1.5.1 github.com/fsnotify/fsnotify v1.5.1
github.com/ghodss/yaml v1.0.0 github.com/ghodss/yaml v1.0.0
github.com/godbus/dbus/v5 v5.0.4 github.com/godbus/dbus/v5 v5.0.5
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf
github.com/google/uuid v1.3.0 github.com/google/uuid v1.3.0
github.com/gorilla/mux v1.8.0 github.com/gorilla/mux v1.8.0

3
go.sum
View File

@ -402,8 +402,9 @@ github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblf
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e h1:BWhy2j3IXJhjCbC68FptL43tDKIq8FladmaTs3Xs7Z8= github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e h1:BWhy2j3IXJhjCbC68FptL43tDKIq8FladmaTs3Xs7Z8=
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.0.5 h1:9Eg0XUhQxtkV8ykTMKtMMYY72g4NgxtRq4jgh4Ih5YM=
github.com/godbus/dbus/v5 v5.0.5/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU=
github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c=

View File

@ -14,14 +14,12 @@ D-Bus message bus system.
### Installation ### Installation
This packages requires Go 1.7. If you installed it and set up your GOPATH, just run: This packages requires Go 1.12 or later. It can be installed by running the command below:
``` ```
go get github.com/godbus/dbus go get github.com/godbus/dbus/v5
``` ```
If you want to use the subpackages, you can install them the same way.
### Usage ### Usage
The complete package documentation and some simple examples are available at The complete package documentation and some simple examples are available at
@ -30,10 +28,12 @@ The complete package documentation and some simple examples are available at
gives a short overview over the basic usage. gives a short overview over the basic usage.
#### Projects using godbus #### Projects using godbus
- [notify](https://github.com/esiqveland/notify) provides desktop notifications over dbus into a library. - [fyne](https://github.com/fyne-io/fyne) a cross platform GUI in Go inspired by Material Design.
- [fynedesk](https://github.com/fyne-io/fynedesk) a full desktop environment for Linux/Unix using Fyne.
- [go-bluetooth](https://github.com/muka/go-bluetooth) provides a bluetooth client over bluez dbus API. - [go-bluetooth](https://github.com/muka/go-bluetooth) provides a bluetooth client over bluez dbus API.
- [playerbm](https://github.com/altdesktop/playerbm) a bookmark utility for media players.
- [iwd](https://github.com/shibumi/iwd) go bindings for the internet wireless daemon "iwd". - [iwd](https://github.com/shibumi/iwd) go bindings for the internet wireless daemon "iwd".
- [notify](https://github.com/esiqveland/notify) provides desktop notifications over dbus into a library.
- [playerbm](https://github.com/altdesktop/playerbm) a bookmark utility for media players.
Please note that the API is considered unstable for now and may change without Please note that the API is considered unstable for now and may change without
further notice. further notice.

View File

@ -75,9 +75,9 @@ func (conn *Conn) Auth(methods []Auth) error {
s = s[1:] s = s[1:]
for _, v := range s { for _, v := range s {
for _, m := range methods { for _, m := range methods {
if name, data, status := m.FirstData(); bytes.Equal(v, name) { if name, _, status := m.FirstData(); bytes.Equal(v, name) {
var ok bool var ok bool
err = authWriteLine(conn.transport, []byte("AUTH"), v, data) err = authWriteLine(conn.transport, []byte("AUTH"), v)
if err != nil { if err != nil {
return err return err
} }
@ -194,11 +194,14 @@ func (conn *Conn) tryAuth(m Auth, state authState, in *bufio.Reader) (error, boo
} }
conn.uuid = string(s[1]) conn.uuid = string(s[1])
return nil, true return nil, true
case state == waitingForOk && string(s[0]) == "DATA":
err = authWriteLine(conn.transport, []byte("DATA"))
if err != nil {
return err, false
}
case state == waitingForOk && string(s[0]) == "REJECTED": case state == waitingForOk && string(s[0]) == "REJECTED":
return nil, false return nil, false
case state == waitingForOk && (string(s[0]) == "DATA" || case state == waitingForOk && string(s[0]) == "ERROR":
string(s[0]) == "ERROR"):
err = authWriteLine(conn.transport, []byte("CANCEL")) err = authWriteLine(conn.transport, []byte("CANCEL"))
if err != nil { if err != nil {
return err, false return err, false

View File

@ -478,14 +478,24 @@ func (conn *Conn) sendMessageAndIfClosed(msg *Message, ifClosed func()) {
conn.outInt(msg) conn.outInt(msg)
} }
err := conn.outHandler.sendAndIfClosed(msg, ifClosed) err := conn.outHandler.sendAndIfClosed(msg, ifClosed)
conn.calls.handleSendError(msg, err)
if err != nil { if err != nil {
conn.serialGen.RetireSerial(msg.serial) conn.handleSendError(msg, err)
} else if msg.Type != TypeMethodCall { } else if msg.Type != TypeMethodCall {
conn.serialGen.RetireSerial(msg.serial) conn.serialGen.RetireSerial(msg.serial)
} }
} }
func (conn *Conn) handleSendError(msg *Message, err error) {
if msg.Type == TypeMethodCall {
conn.calls.handleSendError(msg, err)
} else if msg.Type == TypeMethodReply {
if _, ok := err.(FormatError); ok {
conn.sendError(err, msg.Headers[FieldDestination].value.(string), msg.Headers[FieldReplySerial].value.(uint32))
}
}
conn.serialGen.RetireSerial(msg.serial)
}
// Send sends the given message to the message bus. You usually don't need to // Send sends the given message to the message bus. You usually don't need to
// use this; use the higher-level equivalents (Call / Go, Emit and Export) // use this; use the higher-level equivalents (Call / Go, Emit and Export)
// instead. If msg is a method call and NoReplyExpected is not set, a non-nil // instead. If msg is a method call and NoReplyExpected is not set, a non-nil

View File

@ -10,14 +10,16 @@ type decoder struct {
in io.Reader in io.Reader
order binary.ByteOrder order binary.ByteOrder
pos int pos int
fds []int
} }
// newDecoder returns a new decoder that reads values from in. The input is // newDecoder returns a new decoder that reads values from in. The input is
// expected to be in the given byte order. // expected to be in the given byte order.
func newDecoder(in io.Reader, order binary.ByteOrder) *decoder { func newDecoder(in io.Reader, order binary.ByteOrder, fds []int) *decoder {
dec := new(decoder) dec := new(decoder)
dec.in = in dec.in = in
dec.order = order dec.order = order
dec.fds = fds
return dec return dec
} }
@ -53,7 +55,7 @@ func (dec *decoder) Decode(sig Signature) (vs []interface{}, err error) {
vs = make([]interface{}, 0) vs = make([]interface{}, 0)
s := sig.str s := sig.str
for s != "" { for s != "" {
err, rem := validSingle(s, 0) err, rem := validSingle(s, &depthCounter{})
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -150,7 +152,7 @@ func (dec *decoder) decode(s string, depth int) interface{} {
if len(sig.str) == 0 { if len(sig.str) == 0 {
panic(FormatError("variant signature is empty")) panic(FormatError("variant signature is empty"))
} }
err, rem := validSingle(sig.str, 0) err, rem := validSingle(sig.str, &depthCounter{})
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -161,7 +163,11 @@ func (dec *decoder) decode(s string, depth int) interface{} {
variant.value = dec.decode(sig.str, depth+1) variant.value = dec.decode(sig.str, depth+1)
return variant return variant
case 'h': case 'h':
return UnixFDIndex(dec.decode("u", depth).(uint32)) idx := dec.decode("u", depth).(uint32)
if int(idx) < len(dec.fds) {
return UnixFD(dec.fds[idx])
}
return UnixFDIndex(idx)
case 'a': case 'a':
if len(s) > 1 && s[1] == '{' { if len(s) > 1 && s[1] == '{' {
ksig := s[2:3] ksig := s[2:3]
@ -219,7 +225,7 @@ func (dec *decoder) decode(s string, depth int) interface{} {
v := make([]interface{}, 0) v := make([]interface{}, 0)
s = s[1 : len(s)-1] s = s[1 : len(s)-1]
for s != "" { for s != "" {
err, rem := validSingle(s, 0) err, rem := validSingle(s, &depthCounter{})
if err != nil { if err != nil {
panic(err) panic(err)
} }

View File

@ -5,28 +5,33 @@ import (
"encoding/binary" "encoding/binary"
"io" "io"
"reflect" "reflect"
"strings"
"unicode/utf8"
) )
// An encoder encodes values to the D-Bus wire format. // An encoder encodes values to the D-Bus wire format.
type encoder struct { type encoder struct {
out io.Writer out io.Writer
fds []int
order binary.ByteOrder order binary.ByteOrder
pos int pos int
} }
// NewEncoder returns a new encoder that writes to out in the given byte order. // NewEncoder returns a new encoder that writes to out in the given byte order.
func newEncoder(out io.Writer, order binary.ByteOrder) *encoder { func newEncoder(out io.Writer, order binary.ByteOrder, fds []int) *encoder {
return newEncoderAtOffset(out, 0, order) enc := newEncoderAtOffset(out, 0, order, fds)
return enc
} }
// newEncoderAtOffset returns a new encoder that writes to out in the given // newEncoderAtOffset returns a new encoder that writes to out in the given
// byte order. Specify the offset to initialize pos for proper alignment // byte order. Specify the offset to initialize pos for proper alignment
// computation. // computation.
func newEncoderAtOffset(out io.Writer, offset int, order binary.ByteOrder) *encoder { func newEncoderAtOffset(out io.Writer, offset int, order binary.ByteOrder, fds []int) *encoder {
enc := new(encoder) enc := new(encoder)
enc.out = out enc.out = out
enc.order = order enc.order = order
enc.pos = offset enc.pos = offset
enc.fds = fds
return enc return enc
} }
@ -75,6 +80,9 @@ func (enc *encoder) Encode(vs ...interface{}) (err error) {
// encode encodes the given value to the writer and panics on error. depth holds // encode encodes the given value to the writer and panics on error. depth holds
// the depth of the container nesting. // the depth of the container nesting.
func (enc *encoder) encode(v reflect.Value, depth int) { func (enc *encoder) encode(v reflect.Value, depth int) {
if depth > 64 {
panic(FormatError("input exceeds depth limitation"))
}
enc.align(alignment(v.Type())) enc.align(alignment(v.Type()))
switch v.Kind() { switch v.Kind() {
case reflect.Uint8: case reflect.Uint8:
@ -97,7 +105,14 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
enc.binwrite(uint16(v.Uint())) enc.binwrite(uint16(v.Uint()))
enc.pos += 2 enc.pos += 2
case reflect.Int, reflect.Int32: case reflect.Int, reflect.Int32:
enc.binwrite(int32(v.Int())) if v.Type() == unixFDType {
fd := v.Int()
idx := len(enc.fds)
enc.fds = append(enc.fds, int(fd))
enc.binwrite(uint32(idx))
} else {
enc.binwrite(int32(v.Int()))
}
enc.pos += 4 enc.pos += 4
case reflect.Uint, reflect.Uint32: case reflect.Uint, reflect.Uint32:
enc.binwrite(uint32(v.Uint())) enc.binwrite(uint32(v.Uint()))
@ -112,9 +127,21 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
enc.binwrite(v.Float()) enc.binwrite(v.Float())
enc.pos += 8 enc.pos += 8
case reflect.String: case reflect.String:
enc.encode(reflect.ValueOf(uint32(len(v.String()))), depth) str := v.String()
if !utf8.ValidString(str) {
panic(FormatError("input has a not-utf8 char in string"))
}
if strings.IndexByte(str, byte(0)) != -1 {
panic(FormatError("input has a null char('\\000') in string"))
}
if v.Type() == objectPathType {
if !ObjectPath(str).IsValid() {
panic(FormatError("invalid object path"))
}
}
enc.encode(reflect.ValueOf(uint32(len(str))), depth)
b := make([]byte, v.Len()+1) b := make([]byte, v.Len()+1)
copy(b, v.String()) copy(b, str)
b[len(b)-1] = 0 b[len(b)-1] = 0
n, err := enc.out.Write(b) n, err := enc.out.Write(b)
if err != nil { if err != nil {
@ -124,20 +151,23 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
case reflect.Ptr: case reflect.Ptr:
enc.encode(v.Elem(), depth) enc.encode(v.Elem(), depth)
case reflect.Slice, reflect.Array: case reflect.Slice, reflect.Array:
if depth >= 64 {
panic(FormatError("input exceeds container depth limit"))
}
// Lookahead offset: 4 bytes for uint32 length (with alignment), // Lookahead offset: 4 bytes for uint32 length (with alignment),
// plus alignment for elements. // plus alignment for elements.
n := enc.padding(0, 4) + 4 n := enc.padding(0, 4) + 4
offset := enc.pos + n + enc.padding(n, alignment(v.Type().Elem())) offset := enc.pos + n + enc.padding(n, alignment(v.Type().Elem()))
var buf bytes.Buffer var buf bytes.Buffer
bufenc := newEncoderAtOffset(&buf, offset, enc.order) bufenc := newEncoderAtOffset(&buf, offset, enc.order, enc.fds)
for i := 0; i < v.Len(); i++ { for i := 0; i < v.Len(); i++ {
bufenc.encode(v.Index(i), depth+1) bufenc.encode(v.Index(i), depth+1)
} }
if buf.Len() > 1<<26 {
panic(FormatError("input exceeds array size limitation"))
}
enc.fds = bufenc.fds
enc.encode(reflect.ValueOf(uint32(buf.Len())), depth) enc.encode(reflect.ValueOf(uint32(buf.Len())), depth)
length := buf.Len() length := buf.Len()
enc.align(alignment(v.Type().Elem())) enc.align(alignment(v.Type().Elem()))
@ -146,13 +176,10 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
} }
enc.pos += length enc.pos += length
case reflect.Struct: case reflect.Struct:
if depth >= 64 && v.Type() != signatureType {
panic(FormatError("input exceeds container depth limit"))
}
switch t := v.Type(); t { switch t := v.Type(); t {
case signatureType: case signatureType:
str := v.Field(0) str := v.Field(0)
enc.encode(reflect.ValueOf(byte(str.Len())), depth+1) enc.encode(reflect.ValueOf(byte(str.Len())), depth)
b := make([]byte, str.Len()+1) b := make([]byte, str.Len()+1)
copy(b, str.String()) copy(b, str.String())
b[len(b)-1] = 0 b[len(b)-1] = 0
@ -176,9 +203,6 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
case reflect.Map: case reflect.Map:
// Maps are arrays of structures, so they actually increase the depth by // Maps are arrays of structures, so they actually increase the depth by
// 2. // 2.
if depth >= 63 {
panic(FormatError("input exceeds container depth limit"))
}
if !isKeyType(v.Type().Key()) { if !isKeyType(v.Type().Key()) {
panic(InvalidTypeError{v.Type()}) panic(InvalidTypeError{v.Type()})
} }
@ -189,12 +213,13 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
offset := enc.pos + n + enc.padding(n, 8) offset := enc.pos + n + enc.padding(n, 8)
var buf bytes.Buffer var buf bytes.Buffer
bufenc := newEncoderAtOffset(&buf, offset, enc.order) bufenc := newEncoderAtOffset(&buf, offset, enc.order, enc.fds)
for _, k := range keys { for _, k := range keys {
bufenc.align(8) bufenc.align(8)
bufenc.encode(k, depth+2) bufenc.encode(k, depth+2)
bufenc.encode(v.MapIndex(k), depth+2) bufenc.encode(v.MapIndex(k), depth+2)
} }
enc.fds = bufenc.fds
enc.encode(reflect.ValueOf(uint32(buf.Len())), depth) enc.encode(reflect.ValueOf(uint32(buf.Len())), depth)
length := buf.Len() length := buf.Len()
enc.align(8) enc.align(8)

View File

@ -26,6 +26,27 @@ var (
} }
) )
func MakeNoObjectError(path ObjectPath) Error {
return Error{
"org.freedesktop.DBus.Error.NoSuchObject",
[]interface{}{fmt.Sprintf("No such object '%s'", string(path))},
}
}
func MakeUnknownMethodError(methodName string) Error {
return Error{
"org.freedesktop.DBus.Error.UnknownMethod",
[]interface{}{fmt.Sprintf("Unknown / invalid method '%s'", methodName)},
}
}
func MakeUnknownInterfaceError(ifaceName string) Error {
return Error{
"org.freedesktop.DBus.Error.UnknownInterface",
[]interface{}{fmt.Sprintf("Object does not implement the interface '%s'", ifaceName)},
}
}
func MakeFailedError(err error) *Error { func MakeFailedError(err error) *Error {
return &Error{ return &Error{
"org.freedesktop.DBus.Error.Failed", "org.freedesktop.DBus.Error.Failed",
@ -128,6 +149,11 @@ func (conn *Conn) handleCall(msg *Message) {
ifaceName, _ := msg.Headers[FieldInterface].value.(string) ifaceName, _ := msg.Headers[FieldInterface].value.(string)
sender, hasSender := msg.Headers[FieldSender].value.(string) sender, hasSender := msg.Headers[FieldSender].value.(string)
serial := msg.serial serial := msg.serial
if len(name) == 0 {
conn.sendError(ErrMsgUnknownMethod, sender, serial)
}
if ifaceName == "org.freedesktop.DBus.Peer" { if ifaceName == "org.freedesktop.DBus.Peer" {
switch name { switch name {
case "Ping": case "Ping":
@ -135,29 +161,26 @@ func (conn *Conn) handleCall(msg *Message) {
case "GetMachineId": case "GetMachineId":
conn.sendReply(sender, serial, conn.uuid) conn.sendReply(sender, serial, conn.uuid)
default: default:
conn.sendError(ErrMsgUnknownMethod, sender, serial) conn.sendError(MakeUnknownMethodError(name), sender, serial)
} }
return return
} }
if len(name) == 0 {
conn.sendError(ErrMsgUnknownMethod, sender, serial)
}
object, ok := conn.handler.LookupObject(path) object, ok := conn.handler.LookupObject(path)
if !ok { if !ok {
conn.sendError(ErrMsgNoObject, sender, serial) conn.sendError(MakeNoObjectError(path), sender, serial)
return return
} }
iface, exists := object.LookupInterface(ifaceName) iface, exists := object.LookupInterface(ifaceName)
if !exists { if !exists {
conn.sendError(ErrMsgUnknownInterface, sender, serial) conn.sendError(MakeUnknownInterfaceError(ifaceName), sender, serial)
return return
} }
m, exists := iface.LookupMethod(name) m, exists := iface.LookupMethod(name)
if !exists { if !exists {
conn.sendError(ErrMsgUnknownMethod, sender, serial) conn.sendError(MakeUnknownMethodError(name), sender, serial)
return return
} }
args, err := conn.decodeArguments(m, sender, msg) args, err := conn.decodeArguments(m, sender, msg)

View File

@ -118,11 +118,7 @@ type header struct {
Variant Variant
} }
// DecodeMessage tries to decode a single message in the D-Bus wire format func DecodeMessageWithFDs(rd io.Reader, fds []int) (msg *Message, err error) {
// from the given reader. The byte order is figured out from the first byte.
// The possibly returned error can be an error of the underlying reader, an
// InvalidMessageError or a FormatError.
func DecodeMessage(rd io.Reader) (msg *Message, err error) {
var order binary.ByteOrder var order binary.ByteOrder
var hlength, length uint32 var hlength, length uint32
var typ, flags, proto byte var typ, flags, proto byte
@ -142,7 +138,7 @@ func DecodeMessage(rd io.Reader) (msg *Message, err error) {
return nil, InvalidMessageError("invalid byte order") return nil, InvalidMessageError("invalid byte order")
} }
dec := newDecoder(rd, order) dec := newDecoder(rd, order, fds)
dec.pos = 1 dec.pos = 1
msg = new(Message) msg = new(Message)
@ -166,7 +162,7 @@ func DecodeMessage(rd io.Reader) (msg *Message, err error) {
if hlength+length+16 > 1<<27 { if hlength+length+16 > 1<<27 {
return nil, InvalidMessageError("message is too long") return nil, InvalidMessageError("message is too long")
} }
dec = newDecoder(io.MultiReader(bytes.NewBuffer(b), rd), order) dec = newDecoder(io.MultiReader(bytes.NewBuffer(b), rd), order, fds)
dec.pos = 12 dec.pos = 12
vs, err = dec.Decode(Signature{"a(yv)"}) vs, err = dec.Decode(Signature{"a(yv)"})
if err != nil { if err != nil {
@ -196,7 +192,7 @@ func DecodeMessage(rd io.Reader) (msg *Message, err error) {
sig, _ := msg.Headers[FieldSignature].value.(Signature) sig, _ := msg.Headers[FieldSignature].value.(Signature)
if sig.str != "" { if sig.str != "" {
buf := bytes.NewBuffer(body) buf := bytes.NewBuffer(body)
dec = newDecoder(buf, order) dec = newDecoder(buf, order, fds)
vs, err := dec.Decode(sig) vs, err := dec.Decode(sig)
if err != nil { if err != nil {
return nil, err return nil, err
@ -207,12 +203,32 @@ func DecodeMessage(rd io.Reader) (msg *Message, err error) {
return return
} }
// EncodeTo encodes and sends a message to the given writer. The byte order must // DecodeMessage tries to decode a single message in the D-Bus wire format
// be either binary.LittleEndian or binary.BigEndian. If the message is not // from the given reader. The byte order is figured out from the first byte.
// valid or an error occurs when writing, an error is returned. // The possibly returned error can be an error of the underlying reader, an
func (msg *Message) EncodeTo(out io.Writer, order binary.ByteOrder) error { // InvalidMessageError or a FormatError.
func DecodeMessage(rd io.Reader) (msg *Message, err error) {
return DecodeMessageWithFDs(rd, make([]int, 0));
}
type nullwriter struct{}
func (nullwriter) Write(p []byte) (cnt int, err error) {
return len(p), nil
}
func (msg *Message) CountFds() (int, error) {
if len(msg.Body) == 0 {
return 0, nil
}
enc := newEncoder(nullwriter{}, nativeEndian, make([]int, 0))
err := enc.Encode(msg.Body...)
return len(enc.fds), err
}
func (msg *Message) EncodeToWithFDs(out io.Writer, order binary.ByteOrder) (fds []int, err error) {
if err := msg.IsValid(); err != nil { if err := msg.IsValid(); err != nil {
return err return make([]int, 0), err
} }
var vs [7]interface{} var vs [7]interface{}
switch order { switch order {
@ -221,12 +237,16 @@ func (msg *Message) EncodeTo(out io.Writer, order binary.ByteOrder) error {
case binary.BigEndian: case binary.BigEndian:
vs[0] = byte('B') vs[0] = byte('B')
default: default:
return errors.New("dbus: invalid byte order") return make([]int, 0), errors.New("dbus: invalid byte order")
} }
body := new(bytes.Buffer) body := new(bytes.Buffer)
enc := newEncoder(body, order) fds = make([]int, 0)
enc := newEncoder(body, order, fds)
if len(msg.Body) != 0 { if len(msg.Body) != 0 {
enc.Encode(msg.Body...) err = enc.Encode(msg.Body...)
if err != nil {
return
}
} }
vs[1] = msg.Type vs[1] = msg.Type
vs[2] = msg.Flags vs[2] = msg.Flags
@ -239,17 +259,28 @@ func (msg *Message) EncodeTo(out io.Writer, order binary.ByteOrder) error {
} }
vs[6] = headers vs[6] = headers
var buf bytes.Buffer var buf bytes.Buffer
enc = newEncoder(&buf, order) enc = newEncoder(&buf, order, enc.fds)
enc.Encode(vs[:]...) err = enc.Encode(vs[:]...)
if err != nil {
return
}
enc.align(8) enc.align(8)
body.WriteTo(&buf) body.WriteTo(&buf)
if buf.Len() > 1<<27 { if buf.Len() > 1<<27 {
return InvalidMessageError("message is too long") return make([]int, 0), InvalidMessageError("message is too long")
} }
if _, err := buf.WriteTo(out); err != nil { if _, err := buf.WriteTo(out); err != nil {
return err return make([]int, 0), err
} }
return nil return enc.fds, nil
}
// EncodeTo encodes and sends a message to the given writer. The byte order must
// be either binary.LittleEndian or binary.BigEndian. If the message is not
// valid or an error occurs when writing, an error is returned.
func (msg *Message) EncodeTo(out io.Writer, order binary.ByteOrder) (err error) {
_, err = msg.EncodeToWithFDs(out, order);
return err;
} }
// IsValid checks whether msg is a valid message and returns an // IsValid checks whether msg is a valid message and returns an

View File

@ -34,7 +34,7 @@ type Signature struct {
func SignatureOf(vs ...interface{}) Signature { func SignatureOf(vs ...interface{}) Signature {
var s string var s string
for _, v := range vs { for _, v := range vs {
s += getSignature(reflect.TypeOf(v)) s += getSignature(reflect.TypeOf(v), &depthCounter{})
} }
return Signature{s} return Signature{s}
} }
@ -42,11 +42,19 @@ func SignatureOf(vs ...interface{}) Signature {
// SignatureOfType returns the signature of the given type. It panics if the // SignatureOfType returns the signature of the given type. It panics if the
// type is not representable in D-Bus. // type is not representable in D-Bus.
func SignatureOfType(t reflect.Type) Signature { func SignatureOfType(t reflect.Type) Signature {
return Signature{getSignature(t)} return Signature{getSignature(t, &depthCounter{})}
} }
// getSignature returns the signature of the given type and panics on unknown types. // getSignature returns the signature of the given type and panics on unknown types.
func getSignature(t reflect.Type) string { func getSignature(t reflect.Type, depth *depthCounter) (sig string) {
if !depth.Valid() {
panic("container nesting too deep")
}
defer func() {
if len(sig) > 255 {
panic("signature exceeds the length limitation")
}
}()
// handle simple types first // handle simple types first
switch t.Kind() { switch t.Kind() {
case reflect.Uint8: case reflect.Uint8:
@ -74,7 +82,7 @@ func getSignature(t reflect.Type) string {
case reflect.Float64: case reflect.Float64:
return "d" return "d"
case reflect.Ptr: case reflect.Ptr:
return getSignature(t.Elem()) return getSignature(t.Elem(), depth)
case reflect.String: case reflect.String:
if t == objectPathType { if t == objectPathType {
return "o" return "o"
@ -90,17 +98,20 @@ func getSignature(t reflect.Type) string {
for i := 0; i < t.NumField(); i++ { for i := 0; i < t.NumField(); i++ {
field := t.Field(i) field := t.Field(i)
if field.PkgPath == "" && field.Tag.Get("dbus") != "-" { if field.PkgPath == "" && field.Tag.Get("dbus") != "-" {
s += getSignature(t.Field(i).Type) s += getSignature(t.Field(i).Type, depth.EnterStruct())
} }
} }
if len(s) == 0 {
panic("empty struct")
}
return "(" + s + ")" return "(" + s + ")"
case reflect.Array, reflect.Slice: case reflect.Array, reflect.Slice:
return "a" + getSignature(t.Elem()) return "a" + getSignature(t.Elem(), depth.EnterArray())
case reflect.Map: case reflect.Map:
if !isKeyType(t.Key()) { if !isKeyType(t.Key()) {
panic(InvalidTypeError{t}) panic(InvalidTypeError{t})
} }
return "a{" + getSignature(t.Key()) + getSignature(t.Elem()) + "}" return "a{" + getSignature(t.Key(), depth.EnterArray().EnterDictEntry()) + getSignature(t.Elem(), depth.EnterArray().EnterDictEntry()) + "}"
case reflect.Interface: case reflect.Interface:
return "v" return "v"
} }
@ -118,7 +129,7 @@ func ParseSignature(s string) (sig Signature, err error) {
} }
sig.str = s sig.str = s
for err == nil && len(s) != 0 { for err == nil && len(s) != 0 {
err, s = validSingle(s, 0) err, s = validSingle(s, &depthCounter{})
} }
if err != nil { if err != nil {
sig = Signature{""} sig = Signature{""}
@ -144,7 +155,7 @@ func (s Signature) Empty() bool {
// Single returns whether the signature represents a single, complete type. // Single returns whether the signature represents a single, complete type.
func (s Signature) Single() bool { func (s Signature) Single() bool {
err, r := validSingle(s.str, 0) err, r := validSingle(s.str, &depthCounter{})
return err != nil && r == "" return err != nil && r == ""
} }
@ -164,15 +175,38 @@ func (e SignatureError) Error() string {
return fmt.Sprintf("dbus: invalid signature: %q (%s)", e.Sig, e.Reason) return fmt.Sprintf("dbus: invalid signature: %q (%s)", e.Sig, e.Reason)
} }
type depthCounter struct {
arrayDepth, structDepth, dictEntryDepth int
}
func (cnt *depthCounter) Valid() bool {
return cnt.arrayDepth <= 32 && cnt.structDepth <= 32 && cnt.dictEntryDepth <= 32
}
func (cnt depthCounter) EnterArray() *depthCounter {
cnt.arrayDepth++
return &cnt
}
func (cnt depthCounter) EnterStruct() *depthCounter {
cnt.structDepth++
return &cnt
}
func (cnt depthCounter) EnterDictEntry() *depthCounter {
cnt.dictEntryDepth++
return &cnt
}
// Try to read a single type from this string. If it was successful, err is nil // Try to read a single type from this string. If it was successful, err is nil
// and rem is the remaining unparsed part. Otherwise, err is a non-nil // and rem is the remaining unparsed part. Otherwise, err is a non-nil
// SignatureError and rem is "". depth is the current recursion depth which may // SignatureError and rem is "". depth is the current recursion depth which may
// not be greater than 64 and should be given as 0 on the first call. // not be greater than 64 and should be given as 0 on the first call.
func validSingle(s string, depth int) (err error, rem string) { func validSingle(s string, depth *depthCounter) (err error, rem string) {
if s == "" { if s == "" {
return SignatureError{Sig: s, Reason: "empty signature"}, "" return SignatureError{Sig: s, Reason: "empty signature"}, ""
} }
if depth > 64 { if !depth.Valid() {
return SignatureError{Sig: s, Reason: "container nesting too deep"}, "" return SignatureError{Sig: s, Reason: "container nesting too deep"}, ""
} }
switch s[0] { switch s[0] {
@ -187,10 +221,10 @@ func validSingle(s string, depth int) (err error, rem string) {
i++ i++
rem = s[i+1:] rem = s[i+1:]
s = s[2:i] s = s[2:i]
if err, _ = validSingle(s[:1], depth+1); err != nil { if err, _ = validSingle(s[:1], depth.EnterArray().EnterDictEntry()); err != nil {
return err, "" return err, ""
} }
err, nr := validSingle(s[1:], depth+1) err, nr := validSingle(s[1:], depth.EnterArray().EnterDictEntry())
if err != nil { if err != nil {
return err, "" return err, ""
} }
@ -199,7 +233,7 @@ func validSingle(s string, depth int) (err error, rem string) {
} }
return nil, rem return nil, rem
} }
return validSingle(s[1:], depth+1) return validSingle(s[1:], depth.EnterArray())
case '(': case '(':
i := findMatching(s, '(', ')') i := findMatching(s, '(', ')')
if i == -1 { if i == -1 {
@ -208,7 +242,7 @@ func validSingle(s string, depth int) (err error, rem string) {
rem = s[i+1:] rem = s[i+1:]
s = s[1:i] s = s[1:i]
for err == nil && s != "" { for err == nil && s != "" {
err, s = validSingle(s, depth+1) err, s = validSingle(s, depth.EnterStruct())
} }
if err != nil { if err != nil {
rem = "" rem = ""
@ -236,7 +270,7 @@ func findMatching(s string, left, right rune) int {
// typeFor returns the type of the given signature. It ignores any left over // typeFor returns the type of the given signature. It ignores any left over
// characters and panics if s doesn't start with a valid type signature. // characters and panics if s doesn't start with a valid type signature.
func typeFor(s string) (t reflect.Type) { func typeFor(s string) (t reflect.Type) {
err, _ := validSingle(s, 0) err, _ := validSingle(s, &depthCounter{})
if err != nil { if err != nil {
panic(err) panic(err)
} }

View File

@ -41,10 +41,12 @@ func (t genericTransport) ReadMessage() (*Message, error) {
} }
func (t genericTransport) SendMessage(msg *Message) error { func (t genericTransport) SendMessage(msg *Message) error {
for _, v := range msg.Body { fds, err := msg.CountFds()
if _, ok := v.(UnixFD); ok { if err != nil {
return errors.New("dbus: unix fd passing not enabled") return err
} }
if fds != 0 {
return errors.New("dbus: unix fd passing not enabled")
} }
return msg.EncodeTo(t, nativeEndian) return msg.EncodeTo(t, nativeEndian)
} }

View File

@ -113,7 +113,7 @@ func (t *unixTransport) ReadMessage() (*Message, error) {
if _, err := io.ReadFull(t.rdr, headerdata[4:]); err != nil { if _, err := io.ReadFull(t.rdr, headerdata[4:]); err != nil {
return nil, err return nil, err
} }
dec := newDecoder(bytes.NewBuffer(headerdata), order) dec := newDecoder(bytes.NewBuffer(headerdata), order, make([]int, 0))
dec.pos = 12 dec.pos = 12
vs, err := dec.Decode(Signature{"a(yv)"}) vs, err := dec.Decode(Signature{"a(yv)"})
if err != nil { if err != nil {
@ -147,7 +147,7 @@ func (t *unixTransport) ReadMessage() (*Message, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
msg, err := DecodeMessage(bytes.NewBuffer(all)) msg, err := DecodeMessageWithFDs(bytes.NewBuffer(all), fds)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -179,21 +179,21 @@ func (t *unixTransport) ReadMessage() (*Message, error) {
} }
func (t *unixTransport) SendMessage(msg *Message) error { func (t *unixTransport) SendMessage(msg *Message) error {
fds := make([]int, 0) fdcnt, err := msg.CountFds()
for i, v := range msg.Body { if err != nil {
if fd, ok := v.(UnixFD); ok { return err
msg.Body[i] = UnixFDIndex(len(fds))
fds = append(fds, int(fd))
}
} }
if len(fds) != 0 { if fdcnt != 0 {
if !t.hasUnixFDs { if !t.hasUnixFDs {
return errors.New("dbus: unix fd passing not enabled") return errors.New("dbus: unix fd passing not enabled")
} }
msg.Headers[FieldUnixFDs] = MakeVariant(uint32(len(fds))) msg.Headers[FieldUnixFDs] = MakeVariant(uint32(fdcnt))
oob := syscall.UnixRights(fds...)
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
msg.EncodeTo(buf, nativeEndian) fds, err := msg.EncodeToWithFDs(buf, nativeEndian)
if err != nil {
return err
}
oob := syscall.UnixRights(fds...)
n, oobn, err := t.UnixConn.WriteMsgUnix(buf.Bytes(), oob, nil) n, oobn, err := t.UnixConn.WriteMsgUnix(buf.Bytes(), oob, nil)
if err != nil { if err != nil {
return err return err

2
vendor/modules.txt vendored
View File

@ -348,7 +348,7 @@ github.com/ghodss/yaml
github.com/go-logr/logr github.com/go-logr/logr
# github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 # github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0
github.com/go-task/slim-sprig github.com/go-task/slim-sprig
# github.com/godbus/dbus/v5 v5.0.4 # github.com/godbus/dbus/v5 v5.0.5
github.com/godbus/dbus/v5 github.com/godbus/dbus/v5
# github.com/gogo/protobuf v1.3.2 # github.com/gogo/protobuf v1.3.2
github.com/gogo/protobuf/gogoproto github.com/gogo/protobuf/gogoproto