ceph-csi/e2e/vendor/github.com/godbus/dbus/v5/decoder.go
Niels de Vos f87d06ed85 build: move e2e dependencies into e2e/go.mod
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>
2025-03-04 17:43:49 +01:00

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)
}