From d3055cb9a5f3de01254137677452b90fd4aa02b7 Mon Sep 17 00:00:00 2001 From: Joel Wetzell Date: Sun, 30 Aug 2026 09:00:38 -0500 Subject: [PATCH] rework bundle decoding and tests --- bundle.go | 68 +++++++++++++++++++------------------------------- bundle_test.go | 18 +++++++++++++ 2 files changed, 44 insertions(+), 42 deletions(-) diff --git a/bundle.go b/bundle.go index 0dbe158..ede3a0f 100644 --- a/bundle.go +++ b/bundle.go @@ -45,59 +45,43 @@ func BundleFromBytes(bytes []byte) (*OSCBundle, []byte, error) { return nil, bytesAfterBundleHeader, errors.New("OSC Bundle must start with #bundle string") } - timeTag, bytesAfterTimeTag, err := readOSCTimeTag(bytesAfterBundleHeader) - - if err != nil { - return nil, bytesAfterBundleHeader, err - } + timeTag, bytesAfterTimeTag, _ := readOSCTimeTag(bytesAfterBundleHeader) bundleContents := []OSCPacket{} - endOfBundle := false - remainingBytes := bytesAfterTimeTag - for !endOfBundle { - contentSize, bytesAfterContentSize, err := readOSCInt32(remainingBytes) + contentSize, bytesAfterContentSize, _ := readOSCInt32(remainingBytes) + remainingBytes = bytesAfterContentSize + + if contentSize <= 0 { + return nil, remainingBytes, errors.New("bundle content size must be positive") + } + + if len(remainingBytes) < int(contentSize) { + return nil, remainingBytes, errors.New("bundle doesn't have enough bytes for the content size it specifies") + } + + bundleContentBytes := remainingBytes[0:contentSize] + + switch bundleContentBytes[0] { + case 35: // # + content, _, err := BundleFromBytes(bundleContentBytes) if err != nil { return nil, remainingBytes, err } - - remainingBytes = bytesAfterContentSize - - if contentSize <= 0 { - return nil, remainingBytes, errors.New("bundle content size must be positive") + bundleContents = append(bundleContents, content) + case 47: // / + content, err := MessageFromBytes(bundleContentBytes) + if err != nil { + return nil, remainingBytes, err } - - if len(remainingBytes) < int(contentSize) { - return nil, remainingBytes, errors.New("bundle doesn't have enough bytes for the content size it specifies") - } - - bundleContentBytes := remainingBytes[0:contentSize] - - switch bundleContentBytes[0] { - case 35: // # - content, _, err := BundleFromBytes(bundleContentBytes) - if err != nil { - return nil, remainingBytes, err - } - bundleContents = append(bundleContents, content) - case 47: // / - content, err := MessageFromBytes(bundleContentBytes) - if err != nil { - return nil, remainingBytes, err - } - bundleContents = append(bundleContents, content) - default: - return nil, remainingBytes, errors.New("bundle contents does not look a bundle or message") - } - remainingBytes = bytesAfterContentSize[contentSize:] - if len(remainingBytes) == 0 { - endOfBundle = true - } - + bundleContents = append(bundleContents, content) + default: + return nil, remainingBytes, errors.New("bundle contents does not look a bundle or message") } + remainingBytes = bytesAfterContentSize[contentSize:] return &OSCBundle{ TimeTag: timeTag, diff --git a/bundle_test.go b/bundle_test.go index 22a4790..8fb58ec 100644 --- a/bundle_test.go +++ b/bundle_test.go @@ -194,6 +194,24 @@ func TestBadOSCBundleDecoding(t *testing.T) { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, errorString: "bundle contents does not look a bundle or message", }, + { + name: "bundle with bad bundle inside", + bytes: []byte{35, 98, 117, 110, 100, 108, 101, 0, // #bundle + 0, 0, 0, 32, 0, 0, 0, 0, // time tag + 0, 0, 0, 19, // content size + 35, 98, 117, 110, 100, 108, 101, 0, // #bundle + 0, 0, 0, 64, 0, 0, 0, 0, // time tag + 0, 0, 0}, + errorString: "OSC Bundle has to be at least 20 bytes", + }, + { + name: "bundle with bad message inside", + bytes: []byte{35, 98, 117, 110, 100, 108, 101, 0, // #bundle + 0, 0, 0, 32, 0, 0, 0, 0, // time tag + 0, 0, 0, 5, // content size + 47, 104, 101, 108, 108, 111}, + errorString: "OSC string must be null-terminated", + }, } for _, testCase := range testCases {