From 347491b242096839325d711d2a707d27f78bb01d Mon Sep 17 00:00:00 2001 From: Jonathan Hui Date: Sat, 22 Aug 2026 15:43:51 -0700 Subject: [PATCH] [ip6] fix message buffer leak in otIp6Send() (#13538) `otIp6Send()` promises to transfer ownership of the passed `otMessage` and free it on all paths, including error returns. However, it previously checked `!IsOriginThreadNetif()` before wrapping the message in `OwnedPtr`, causing the message to be leaked when rejected with `OT_ERROR_INVALID_ARGS`. This commit moves the `IsOriginThreadNetif()` check into `Ip6::SendRaw()` in the C++ core, allowing `otIp6Send()` to become a thin pass-through that wraps the message into an `OwnedPtr` up front. This ensures that every return path in `SendRaw()` and `otIp6Send()` takes ownership and frees the message on error. --- src/core/api/ip6_api.cpp | 9 +-------- src/core/net/ip6.cpp | 1 + src/core/net/ip6.hpp | 11 ++++++----- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/core/api/ip6_api.cpp b/src/core/api/ip6_api.cpp index bddb36cdc..8a15e7823 100644 --- a/src/core/api/ip6_api.cpp +++ b/src/core/api/ip6_api.cpp @@ -136,14 +136,7 @@ void otIp6SetReceiveFilterEnabled(otInstance *aInstance, bool aEnabled) otError otIp6Send(otInstance *aInstance, otMessage *aMessage) { - otError error; - - VerifyOrExit(!AsCoreType(aMessage).IsOriginThreadNetif(), error = kErrorInvalidArgs); - - error = AsCoreType(aInstance).Get().SendRaw(OwnedPtr(AsCoreTypePtr(aMessage))); - -exit: - return error; + return AsCoreType(aInstance).Get().SendRaw(OwnedPtr(AsCoreTypePtr(aMessage))); } otMessage *otIp6NewMessage(otInstance *aInstance, const otMessageSettings *aSettings) diff --git a/src/core/net/ip6.cpp b/src/core/net/ip6.cpp index 31ab04292..ee9b82463 100644 --- a/src/core/net/ip6.cpp +++ b/src/core/net/ip6.cpp @@ -1128,6 +1128,7 @@ Error Ip6::SendRaw(OwnedPtr aMessagePtr) Error error = kErrorNone; Header header; + VerifyOrExit(!aMessagePtr->IsOriginThreadNetif(), error = kErrorInvalidArgs); SuccessOrExit(error = header.ParseFrom(*aMessagePtr)); VerifyOrExit(!header.GetSource().IsMulticast(), error = kErrorInvalidSourceAddress); diff --git a/src/core/net/ip6.hpp b/src/core/net/ip6.hpp index eac357a27..749985461 100644 --- a/src/core/net/ip6.hpp +++ b/src/core/net/ip6.hpp @@ -163,11 +163,12 @@ public: * * @param[in] aMessage An owned pointer to a message (ownership is transferred to the method). * - * @retval kErrorNone Successfully processed the message. - * @retval kErrorDrop Message was well-formed but not fully processed due to packet processing rules. - * @retval kErrorNoBufs Could not allocate necessary message buffers when processing the datagram. - * @retval kErrorNoRoute No route to host. - * @retval kErrorParse Encountered a malformed header when processing the message. + * @retval kErrorNone Successfully processed the message. + * @retval kErrorDrop Message was well-formed but not fully processed due to packet processing rules. + * @retval kErrorInvalidArgs The message has invalid origin (`kOriginThreadNetif`). + * @retval kErrorNoBufs Could not allocate necessary message buffers when processing the datagram. + * @retval kErrorNoRoute No route to host. + * @retval kErrorParse Encountered a malformed header when processing the message. */ Error SendRaw(OwnedPtr aMessage);