From 17248d7d6116a4a0b85ed0d90cb382a25eed16b5 Mon Sep 17 00:00:00 2001 From: Ophestra Date: Sun, 14 Dec 2025 06:58:53 +0900 Subject: [PATCH] internal/pipewire: unmarshal nil pointer correctly This now calls unmarshalCheckTypeBounds to advance to the next message. Additionally, handling for None value is relocated to a function for reuse by other types. Signed-off-by: Ophestra --- internal/pipewire/pod.go | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/internal/pipewire/pod.go b/internal/pipewire/pod.go index f8a824c..103154a 100644 --- a/internal/pipewire/pod.go +++ b/internal/pipewire/pod.go @@ -384,19 +384,16 @@ func unmarshalValue(data []byte, v reflect.Value, wireSizeP *Word) error { return nil case reflect.Pointer: - if len(data) < SizePrefix { - return ErrEOFPrefix - } - switch SPAKind(binary.NativeEndian.Uint32(data[SizeSPrefix:])) { - case SPA_TYPE_None: + if ok, err := unmarshalHandleNone(&data, wireSizeP); err != nil { + return err + } else if ok { v.SetZero() return nil - - default: - v.Set(reflect.New(v.Type().Elem())) - return unmarshalValue(data, v.Elem(), wireSizeP) } + v.Set(reflect.New(v.Type().Elem())) + return unmarshalValue(data, v.Elem(), wireSizeP) + case reflect.String: *wireSizeP = 0 if err := unmarshalCheckTypeBounds(&data, SPA_TYPE_String, wireSizeP); err != nil { @@ -422,6 +419,29 @@ func unmarshalValue(data []byte, v reflect.Value, wireSizeP *Word) error { } } +// unmarshalHandleNone establishes prefix bounds and, for a value of type [SPA_TYPE_None], +// validates its size and skips the header. This is for unmarshalling values that can be nil. +func unmarshalHandleNone(data *[]byte, wireSizeP *Word) (bool, error) { + if len(*data) < SizePrefix { + return false, ErrEOFPrefix + } + + if SPAKind(binary.NativeEndian.Uint32((*data)[SizeSPrefix:])) != SPA_TYPE_None { + return false, nil + } + + *wireSizeP = 0 + if err := unmarshalCheckTypeBounds(data, SPA_TYPE_None, wireSizeP); err != nil { + return true, err + } + + if len(*data) != 0 { + return true, TrailingGarbageError(*data) + } + + return true, nil +} + // An InconsistentSizeError describes an inconsistent size prefix encountered // in data passed to [Unmarshal]. type InconsistentSizeError struct{ Prefix, Expect Word }