mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-03-08 16:39:29 +00:00
Several packages are only used while running the e2e suite. These packages are less important to update, as the they can not influence the final executable that is part of the Ceph-CSI container-image. By moving these dependencies out of the main Ceph-CSI go.mod, it is easier to identify if a reported CVE affects Ceph-CSI, or only the testing (like most of the Kubernetes CVEs). Signed-off-by: Niels de Vos <ndevos@ibm.com>
293 lines
6.5 KiB
Go
293 lines
6.5 KiB
Go
package dbus
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"io"
|
|
"reflect"
|
|
)
|
|
|
|
type decoder struct {
|
|
in io.Reader
|
|
order binary.ByteOrder
|
|
pos int
|
|
fds []int
|
|
}
|
|
|
|
// newDecoder returns a new decoder that reads values from in. The input is
|
|
// expected to be in the given byte order.
|
|
func newDecoder(in io.Reader, order binary.ByteOrder, fds []int) *decoder {
|
|
dec := new(decoder)
|
|
dec.in = in
|
|
dec.order = order
|
|
dec.fds = fds
|
|
return dec
|
|
}
|
|
|
|
// align aligns the input to the given boundary and panics on error.
|
|
func (dec *decoder) align(n int) {
|
|
if dec.pos%n != 0 {
|
|
newpos := (dec.pos + n - 1) & ^(n - 1)
|
|
empty := make([]byte, newpos-dec.pos)
|
|
if _, err := io.ReadFull(dec.in, empty); err != nil {
|
|
panic(err)
|
|
}
|
|
dec.pos = newpos
|
|
}
|
|
}
|
|
|
|
// Calls binary.Read(dec.in, dec.order, v) and panics on read errors.
|
|
func (dec *decoder) binread(v interface{}) {
|
|
if err := binary.Read(dec.in, dec.order, v); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
func (dec *decoder) Decode(sig Signature) (vs []interface{}, err error) {
|
|
defer func() {
|
|
var ok bool
|
|
v := recover()
|
|
if err, ok = v.(error); ok {
|
|
if err == io.EOF || err == io.ErrUnexpectedEOF {
|
|
err = FormatError("unexpected EOF")
|
|
}
|
|
}
|
|
}()
|
|
vs = make([]interface{}, 0)
|
|
s := sig.str
|
|
for s != "" {
|
|
err, rem := validSingle(s, &depthCounter{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
v := dec.decode(s[:len(s)-len(rem)], 0)
|
|
vs = append(vs, v)
|
|
s = rem
|
|
}
|
|
return vs, nil
|
|
}
|
|
|
|
func (dec *decoder) decode(s string, depth int) interface{} {
|
|
dec.align(alignment(typeFor(s)))
|
|
switch s[0] {
|
|
case 'y':
|
|
var b [1]byte
|
|
if _, err := dec.in.Read(b[:]); err != nil {
|
|
panic(err)
|
|
}
|
|
dec.pos++
|
|
return b[0]
|
|
case 'b':
|
|
i := dec.decode("u", depth).(uint32)
|
|
switch {
|
|
case i == 0:
|
|
return false
|
|
case i == 1:
|
|
return true
|
|
default:
|
|
panic(FormatError("invalid value for boolean"))
|
|
}
|
|
case 'n':
|
|
var i int16
|
|
dec.binread(&i)
|
|
dec.pos += 2
|
|
return i
|
|
case 'i':
|
|
var i int32
|
|
dec.binread(&i)
|
|
dec.pos += 4
|
|
return i
|
|
case 'x':
|
|
var i int64
|
|
dec.binread(&i)
|
|
dec.pos += 8
|
|
return i
|
|
case 'q':
|
|
var i uint16
|
|
dec.binread(&i)
|
|
dec.pos += 2
|
|
return i
|
|
case 'u':
|
|
var i uint32
|
|
dec.binread(&i)
|
|
dec.pos += 4
|
|
return i
|
|
case 't':
|
|
var i uint64
|
|
dec.binread(&i)
|
|
dec.pos += 8
|
|
return i
|
|
case 'd':
|
|
var f float64
|
|
dec.binread(&f)
|
|
dec.pos += 8
|
|
return f
|
|
case 's':
|
|
length := dec.decode("u", depth).(uint32)
|
|
b := make([]byte, int(length)+1)
|
|
if _, err := io.ReadFull(dec.in, b); err != nil {
|
|
panic(err)
|
|
}
|
|
dec.pos += int(length) + 1
|
|
return string(b[:len(b)-1])
|
|
case 'o':
|
|
return ObjectPath(dec.decode("s", depth).(string))
|
|
case 'g':
|
|
length := dec.decode("y", depth).(byte)
|
|
b := make([]byte, int(length)+1)
|
|
if _, err := io.ReadFull(dec.in, b); err != nil {
|
|
panic(err)
|
|
}
|
|
dec.pos += int(length) + 1
|
|
sig, err := ParseSignature(string(b[:len(b)-1]))
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return sig
|
|
case 'v':
|
|
if depth >= 64 {
|
|
panic(FormatError("input exceeds container depth limit"))
|
|
}
|
|
var variant Variant
|
|
sig := dec.decode("g", depth).(Signature)
|
|
if len(sig.str) == 0 {
|
|
panic(FormatError("variant signature is empty"))
|
|
}
|
|
err, rem := validSingle(sig.str, &depthCounter{})
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
if rem != "" {
|
|
panic(FormatError("variant signature has multiple types"))
|
|
}
|
|
variant.sig = sig
|
|
variant.value = dec.decode(sig.str, depth+1)
|
|
return variant
|
|
case 'h':
|
|
idx := dec.decode("u", depth).(uint32)
|
|
if int(idx) < len(dec.fds) {
|
|
return UnixFD(dec.fds[idx])
|
|
}
|
|
return UnixFDIndex(idx)
|
|
case 'a':
|
|
if len(s) > 1 && s[1] == '{' {
|
|
ksig := s[2:3]
|
|
vsig := s[3 : len(s)-1]
|
|
v := reflect.MakeMap(reflect.MapOf(typeFor(ksig), typeFor(vsig)))
|
|
if depth >= 63 {
|
|
panic(FormatError("input exceeds container depth limit"))
|
|
}
|
|
length := dec.decode("u", depth).(uint32)
|
|
// Even for empty maps, the correct padding must be included
|
|
dec.align(8)
|
|
spos := dec.pos
|
|
for dec.pos < spos+int(length) {
|
|
dec.align(8)
|
|
if !isKeyType(v.Type().Key()) {
|
|
panic(InvalidTypeError{v.Type()})
|
|
}
|
|
kv := dec.decode(ksig, depth+2)
|
|
vv := dec.decode(vsig, depth+2)
|
|
v.SetMapIndex(reflect.ValueOf(kv), reflect.ValueOf(vv))
|
|
}
|
|
return v.Interface()
|
|
}
|
|
if depth >= 64 {
|
|
panic(FormatError("input exceeds container depth limit"))
|
|
}
|
|
sig := s[1:]
|
|
length := dec.decode("u", depth).(uint32)
|
|
// capacity can be determined only for fixed-size element types
|
|
var capacity int
|
|
if s := sigByteSize(sig); s != 0 {
|
|
capacity = int(length) / s
|
|
}
|
|
v := reflect.MakeSlice(reflect.SliceOf(typeFor(sig)), 0, capacity)
|
|
// Even for empty arrays, the correct padding must be included
|
|
align := alignment(typeFor(s[1:]))
|
|
if len(s) > 1 && s[1] == '(' {
|
|
//Special case for arrays of structs
|
|
//structs decode as a slice of interface{} values
|
|
//but the dbus alignment does not match this
|
|
align = 8
|
|
}
|
|
dec.align(align)
|
|
spos := dec.pos
|
|
for dec.pos < spos+int(length) {
|
|
ev := dec.decode(s[1:], depth+1)
|
|
v = reflect.Append(v, reflect.ValueOf(ev))
|
|
}
|
|
return v.Interface()
|
|
case '(':
|
|
if depth >= 64 {
|
|
panic(FormatError("input exceeds container depth limit"))
|
|
}
|
|
dec.align(8)
|
|
v := make([]interface{}, 0)
|
|
s = s[1 : len(s)-1]
|
|
for s != "" {
|
|
err, rem := validSingle(s, &depthCounter{})
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
ev := dec.decode(s[:len(s)-len(rem)], depth+1)
|
|
v = append(v, ev)
|
|
s = rem
|
|
}
|
|
return v
|
|
default:
|
|
panic(SignatureError{Sig: s})
|
|
}
|
|
}
|
|
|
|
// sigByteSize tries to calculates size of the given signature in bytes.
|
|
//
|
|
// It returns zero when it can't, for example when it contains non-fixed size
|
|
// types such as strings, maps and arrays that require reading of the transmitted
|
|
// data, for that we would need to implement the unread method for Decoder first.
|
|
func sigByteSize(sig string) int {
|
|
var total int
|
|
for offset := 0; offset < len(sig); {
|
|
switch sig[offset] {
|
|
case 'y':
|
|
total += 1
|
|
offset += 1
|
|
case 'n', 'q':
|
|
total += 2
|
|
offset += 1
|
|
case 'b', 'i', 'u', 'h':
|
|
total += 4
|
|
offset += 1
|
|
case 'x', 't', 'd':
|
|
total += 8
|
|
offset += 1
|
|
case '(':
|
|
i := 1
|
|
depth := 1
|
|
for i < len(sig[offset:]) && depth != 0 {
|
|
if sig[offset+i] == '(' {
|
|
depth++
|
|
} else if sig[offset+i] == ')' {
|
|
depth--
|
|
}
|
|
i++
|
|
}
|
|
s := sigByteSize(sig[offset+1 : offset+i-1])
|
|
if s == 0 {
|
|
return 0
|
|
}
|
|
total += s
|
|
offset += i
|
|
default:
|
|
return 0
|
|
}
|
|
}
|
|
return total
|
|
}
|
|
|
|
// A FormatError is an error in the wire format.
|
|
type FormatError string
|
|
|
|
func (e FormatError) Error() string {
|
|
return "dbus: wire format error: " + string(e)
|
|
}
|