This is an automated email from the ASF dual-hosted git repository.

sjanc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-newtmgr.git

commit e6e7ee06f4ea6d683ea71f5743c0d4fd1548b3fd
Author: Szymon Janc <[email protected]>
AuthorDate: Thu Oct 22 00:38:13 2026 +0200

    nmxact/udp: Use a new RX buffer for each datagram
    
    The UDP receive loop read every datagram into the same buffer and
    passed a slice of it to the dispatch callback. For OMP the callback
    does not consume the data synchronously: the parsed CoAP message keeps
    referring to the buffer (its payload is a sub-slice) and is decoded
    later by the OMP listener goroutine. A datagram arriving in the
    meantime (e.g. a retransmission or another response) overwrote the
    payload of the previous one, so a response could be decoded from
    corrupted data, and the decode raced with the next read.
    
    Allocate a fresh buffer per datagram.
    
    Assisted-by: Claude:claude-opus-5-5
---
 nmxact/udp/udp.go      |  8 ++++++--
 nmxact/udp/udp_test.go | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 57 insertions(+), 2 deletions(-)

diff --git a/nmxact/udp/udp.go b/nmxact/udp/udp.go
index 8a00c14..c74475b 100644
--- a/nmxact/udp/udp.go
+++ b/nmxact/udp/udp.go
@@ -45,9 +45,13 @@ func Listen(peerString string, dispatchCb func(data []byte)) 
(
        }
 
        go func() {
-               data := make([]byte, MAX_PACKET_SIZE)
-
                for {
+                       // Use a new buffer for each datagram.  The callback 
may hand
+                       // the data to another goroutine (e.g. a CoAP message 
payload
+                       // refers to it), so it must not be overwritten by the 
next
+                       // read.
+                       data := make([]byte, MAX_PACKET_SIZE)
+
                        nr, srcAddr, err := conn.ReadFromUDP(data)
                        if err != nil {
                                // Connection closed or read error.
diff --git a/nmxact/udp/udp_test.go b/nmxact/udp/udp_test.go
index 4b1b12f..4a9efcc 100644
--- a/nmxact/udp/udp_test.go
+++ b/nmxact/udp/udp_test.go
@@ -444,3 +444,54 @@ func TestUdpXportStartStop(t *testing.T) {
                t.Errorf("BuildSesn returned %T, want *UdpSesn", s)
        }
 }
+
+// The dispatch callback may hand the received data to another goroutine
+// (OMP responses are decoded asynchronously and the CoAP payload refers to
+// the input buffer), so each datagram must get its own buffer rather than
+// being overwritten by the next one.
+func TestListenBufferNotReused(t *testing.T) {
+       dev, err := net.ListenUDP("udp",
+               &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 0})
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer dev.Close()
+
+       rx := make(chan []byte, 2)
+       conn, _, err := Listen(dev.LocalAddr().String(), func(data []byte) {
+               rx <- data
+       })
+       if err != nil {
+               t.Fatalf("Listen failed: %v", err)
+       }
+       defer conn.Close()
+
+       dst := &net.UDPAddr{
+               IP:   net.IPv4(127, 0, 0, 1),
+               Port: conn.LocalAddr().(*net.UDPAddr).Port,
+       }
+       for _, s := range []string{"first", "SECND"} {
+               if _, err := dev.WriteToUDP([]byte(s), dst); err != nil {
+                       t.Fatal(err)
+               }
+       }
+
+       var bufs [][]byte
+       for i := 0; i < 2; i++ {
+               select {
+               case b := <-rx:
+                       bufs = append(bufs, b)
+               case <-time.After(testTimeout):
+                       t.Fatalf("timeout waiting for datagram %d", i)
+               }
+       }
+
+       // Both datagrams have been received; the first slice must still hold
+       // the first datagram.
+       if string(bufs[0]) != "first" {
+               t.Errorf("first datagram = %q, want %q", bufs[0], "first")
+       }
+       if string(bufs[1]) != "SECND" {
+               t.Errorf("second datagram = %q", bufs[1])
+       }
+}

Reply via email to