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

xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 86bd7f0edc3f0e568fd43fa5b0db703fd659fe12
Author: raiden00pl <[email protected]>
AuthorDate: Thu Oct 22 14:58:41 2026 +0200

    wireless/ieee802154: free the frame and the confirm with the TX descriptor
    
    The TX descriptor owns its frame and its confirm primitive, but each
    user freed them by hand, and MCPS-DATA.request freed the descriptor
    without its confirm on every error exit, leaking a primitive.
    mac802154_txdesc_free() frees both; a user that hands the confirm to
    the next layer takes it out of the descriptor first.
    
    Assisted-by: Claude Code
    Signed-off-by: raiden00pl <[email protected]>
---
 wireless/ieee802154/mac802154.c          | 21 +++++----------------
 wireless/ieee802154/mac802154_assoc.c    | 16 ++++------------
 wireless/ieee802154/mac802154_data.c     |  2 +-
 wireless/ieee802154/mac802154_internal.h | 26 ++++++++++++++++++++++++++
 wireless/ieee802154/mac802154_poll.c     |  6 +-----
 5 files changed, 37 insertions(+), 34 deletions(-)

diff --git a/wireless/ieee802154/mac802154.c b/wireless/ieee802154/mac802154.c
index a8e2913f7d0..d9aa3d5c0c1 100644
--- a/wireless/ieee802154/mac802154.c
+++ b/wireless/ieee802154/mac802154.c
@@ -775,11 +775,8 @@ static void mac802154_purge_worker(FAR void *arg)
 
           sq_remfirst(&priv->indirect_queue);
 
-          /* Free the IOB, the notification, and the tx descriptor */
+          /* Free the tx descriptor with the frame and the confirm */
 
-          iob_free(txdesc->frame);
-          ieee802154_primitive_free((FAR struct ieee802154_primitive_s *)
-                                    txdesc->conf);
           mac802154_txdesc_free(priv, txdesc);
           priv->beaconupdate = true;
 
@@ -926,12 +923,6 @@ static void mac802154_txdone_worker(FAR void *arg)
           break;
         }
 
-      /* Cast the data_conf to a notification. We get both the private and
-       * public notification structure to make it easier to use.
-       */
-
-      primitive = (FAR struct ieee802154_primitive_s *)txdesc->conf;
-
       wlinfo("Tx status: %s\n",
              g_ieee802154_status_string[txdesc->conf->status]);
 
@@ -939,6 +930,9 @@ static void mac802154_txdone_worker(FAR void *arg)
         {
           case IEEE802154_FRAME_DATA:
             {
+              /* The data confirm goes to the next layer */
+
+              primitive = mac802154_txdesc_takeconf(txdesc);
               primitive->type = IEEE802154_PRIMITIVE_CONF_DATA;
               mac802154_notify(priv, primitive);
             }
@@ -1003,22 +997,17 @@ static void mac802154_txdone_worker(FAR void *arg)
                     break;
 
                   default:
-                    ieee802154_primitive_free(primitive);
                     break;
                 }
             }
             break;
 
           default:
-            {
-              ieee802154_primitive_free(primitive);
-            }
             break;
         }
 
-      /* Free the IOB and the tx descriptor */
+      /* Free the tx descriptor with the frame and an unused confirm */
 
-      iob_free(txdesc->frame);
       mac802154_txdesc_free(priv, txdesc);
     }
 
diff --git a/wireless/ieee802154/mac802154_assoc.c 
b/wireless/ieee802154/mac802154_assoc.c
index c8cb356925e..52482a6b931 100644
--- a/wireless/ieee802154/mac802154_assoc.c
+++ b/wireless/ieee802154/mac802154_assoc.c
@@ -442,8 +442,7 @@ void mac802154_txdone_assocreq(FAR struct 
ieee802154_privmac_s *priv,
                                FAR struct ieee802154_txdesc_s *txdesc)
 {
   enum ieee802154_status_e status;
-  FAR struct ieee802154_primitive_s *primitive =
-    (FAR struct ieee802154_primitive_s *)txdesc->conf;
+  FAR struct ieee802154_primitive_s *primitive;
 
   if (txdesc->conf->status != IEEE802154_STATUS_SUCCESS)
     {
@@ -459,7 +458,8 @@ void mac802154_txdone_assocreq(FAR struct 
ieee802154_privmac_s *priv,
        * why the tx failed from the radio layer.
        */
 
-      status = txdesc->conf->status;
+      status    = txdesc->conf->status;
+      primitive = mac802154_txdesc_takeconf(txdesc);
       primitive->type = IEEE802154_PRIMITIVE_CONF_ASSOC;
 
       primitive->u.assocconf.status = status;
@@ -546,10 +546,6 @@ void mac802154_txdone_assocreq(FAR struct 
ieee802154_privmac_s *priv,
           work_queue(LPWORK, &priv->macop_work, mac802154_extract_assocresp,
                      priv, 0);
         }
-
-      /* Deallocate the data conf notification as it is no longer needed. */
-
-      ieee802154_primitive_free(primitive);
     }
 }
 
@@ -617,7 +613,7 @@ void mac802154_txdone_datareq_assoc(FAR struct 
ieee802154_privmac_s *priv,
       priv->cmd_desc = NULL;
       nxsem_post(&priv->opsem);
 
-      mac802154_notify(priv, primitive);
+      mac802154_notify(priv, mac802154_txdesc_takeconf(txdesc));
     }
   else
     {
@@ -649,10 +645,6 @@ void mac802154_txdone_datareq_assoc(FAR struct 
ieee802154_privmac_s *priv,
           mac802154_timerstart(priv, priv->max_frame_waittime,
                                mac802154_assoctimeout);
         }
-
-      /* Deallocate the data conf notification as it is no longer needed. */
-
-      ieee802154_primitive_free(primitive);
     }
 }
 
diff --git a/wireless/ieee802154/mac802154_data.c 
b/wireless/ieee802154/mac802154_data.c
index 75d6905500d..bf49b6ac131 100644
--- a/wireless/ieee802154/mac802154_data.c
+++ b/wireless/ieee802154/mac802154_data.c
@@ -350,7 +350,7 @@ int mac802154_req_data(MACHANDLE mac,
 
 errout_with_txdesc:
 
-  /* Free TX the descriptor, but preserve the IOB. */
+  /* Free the TX descriptor and its confirm, but preserve the IOB */
 
   txdesc->frame = NULL;
   mac802154_txdesc_free(priv, txdesc);
diff --git a/wireless/ieee802154/mac802154_internal.h 
b/wireless/ieee802154/mac802154_internal.h
index e97e6231de3..0656a4775e4 100644
--- a/wireless/ieee802154/mac802154_internal.h
+++ b/wireless/ieee802154/mac802154_internal.h
@@ -39,6 +39,7 @@
 #include <nuttx/wqueue.h>
 #include <nuttx/mutex.h>
 #include <nuttx/semaphore.h>
+#include <nuttx/mm/iob.h>
 
 #include <nuttx/wireless/ieee802154/ieee802154_mac.h>
 #include <nuttx/wireless/ieee802154/ieee802154_radio.h>
@@ -515,10 +516,35 @@ void mac802154_notify(FAR struct ieee802154_privmac_s 
*priv,
 
 /* General helpers **********************************************************/
 
+/* A tx descriptor owns its frame and its confirm primitive.  A user that
+ * hands the confirm to the next layer takes it out of the descriptor first.
+ */
+
+static inline FAR struct ieee802154_primitive_s *
+mac802154_txdesc_takeconf(FAR struct ieee802154_txdesc_s *txdesc)
+{
+  FAR struct ieee802154_primitive_s *primitive =
+    (FAR struct ieee802154_primitive_s *)txdesc->conf;
+
+  txdesc->conf = NULL;
+  return primitive;
+}
+
 static inline void
 mac802154_txdesc_free(FAR struct ieee802154_privmac_s *priv,
                       FAR struct ieee802154_txdesc_s *txdesc)
 {
+  if (txdesc->frame != NULL)
+    {
+      iob_free(txdesc->frame);
+      txdesc->frame = NULL;
+    }
+
+  if (txdesc->conf != NULL)
+    {
+      ieee802154_primitive_free(mac802154_txdesc_takeconf(txdesc));
+    }
+
   sq_addlast((FAR sq_entry_t *)txdesc, &priv->txdesc_queue);
   nxsem_post(&priv->txdesc_sem);
 }
diff --git a/wireless/ieee802154/mac802154_poll.c 
b/wireless/ieee802154/mac802154_poll.c
index 57b9acc1d38..f32993601f0 100644
--- a/wireless/ieee802154/mac802154_poll.c
+++ b/wireless/ieee802154/mac802154_poll.c
@@ -212,7 +212,7 @@ void mac802154_txdone_datareq_poll(FAR struct 
ieee802154_privmac_s *priv,
       priv->cmd_desc = NULL;
       nxsem_post(&priv->opsem);
 
-      mac802154_notify(priv, primitive);
+      mac802154_notify(priv, mac802154_txdesc_takeconf(txdesc));
     }
   else
     {
@@ -231,10 +231,6 @@ void mac802154_txdone_datareq_poll(FAR struct 
ieee802154_privmac_s *priv,
 
       mac802154_timerstart(priv, priv->max_frame_waittime,
                            mac802154_polltimeout);
-
-      /* Deallocate the data conf primitive as it is no longer needed. */
-
-      ieee802154_primitive_free(primitive);
     }
 }
 

Reply via email to