diff --git a/include/openthread/dns.h b/include/openthread/dns.h index 93fd287d7..0d02dd27e 100644 --- a/include/openthread/dns.h +++ b/include/openthread/dns.h @@ -62,6 +62,8 @@ extern "C" { #define OT_DNS_TXT_KEY_MAX_LENGTH 9 ///< Recommended maximum length of TXT record key string (RFC 6763 - section 6.4). +#define OT_DNS_TXT_KEY_ITER_MAX_LENGTH 64 ///< Maximum length of TXT key string supported by `otDnsTxtEntryIterator`. + /** * Represents a TXT record entry representing a key/value pair (RFC 6763 - section 6.3). * @@ -104,7 +106,7 @@ typedef struct otDnsTxtEntryIterator { const void *mPtr; uint16_t mData[2]; - char mChar[OT_DNS_TXT_KEY_MAX_LENGTH + 1]; + char mChar[OT_DNS_TXT_KEY_ITER_MAX_LENGTH + 1]; } otDnsTxtEntryIterator; /** @@ -127,9 +129,9 @@ void otDnsInitTxtEntryIterator(otDnsTxtEntryIterator *aIterator, const uint8_t * * data buffer used to initialize the iterator MUST persist and remain unchanged. Otherwise the behavior of this * function is undefined. * - * If the parsed key string length is smaller than or equal to `OT_DNS_TXT_KEY_MAX_LENGTH` (recommended max key length) - * the key string is returned in `mKey` in @p aEntry. But if the key is longer, then `mKey` is set to NULL and the - * entire encoded TXT entry string is returned in `mValue` and `mValueLength`. + * If the parsed key string length is smaller than or equal to `OT_DNS_TXT_KEY_ITER_MAX_LENGTH` the key string is + * returned in `mKey` in @p aEntry. But if the key is longer, then `mKey` is set to NULL and the entire encoded TXT + * entry string is returned in `mValue` and `mValueLength`. * * @param[in] aIterator A pointer to the iterator (MUST NOT be NULL). * @param[out] aEntry A pointer to a `otDnsTxtEntry` structure to output the parsed/read entry (MUST NOT be NULL). diff --git a/include/openthread/instance.h b/include/openthread/instance.h index 1ff946b0d..fdcdf6b55 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -53,7 +53,7 @@ extern "C" { * @note This number versions both OpenThread platform and user APIs. * */ -#define OPENTHREAD_API_VERSION (371) +#define OPENTHREAD_API_VERSION (373) /** * @addtogroup api-instance diff --git a/src/core/net/dns_types.cpp b/src/core/net/dns_types.cpp index a9585a22c..2f7f3c99a 100644 --- a/src/core/net/dns_types.cpp +++ b/src/core/net/dns_types.cpp @@ -953,7 +953,7 @@ Error TxtEntry::Iterator::GetNextEntry(TxtEntry &aEntry) const char *cur; char *keyBuffer = GetKeyBuffer(); - static_assert(sizeof(mChar) == TxtEntry::kMaxKeyLength + 1, "KeyBuffer cannot fit the max key length"); + static_assert(sizeof(mChar) >= TxtEntry::kMaxKeyLength + 1, "KeyBuffer cannot fit the max key length"); VerifyOrExit(GetTxtData() != nullptr, error = kErrorParse); @@ -985,9 +985,9 @@ Error TxtEntry::Iterator::GetNextEntry(TxtEntry &aEntry) ExitNow(); } - if (index >= kMaxKeyLength) + if (index >= sizeof(mChar) - 1) { - // The key is larger than recommended max key length. + // The key is larger than supported key string length. // In this case, we return the full encoded string in // `mValue` and `mValueLength` and set `mKey` to // `nullptr`. diff --git a/src/core/net/dns_types.hpp b/src/core/net/dns_types.hpp index 6c9caa4cb..f84d7d361 100644 --- a/src/core/net/dns_types.hpp +++ b/src/core/net/dns_types.hpp @@ -1056,6 +1056,14 @@ public: */ static constexpr uint8_t kMaxKeyLength = OT_DNS_TXT_KEY_MAX_LENGTH; + /** + * Maximum length of TXT key string supported by `Iterator`. + * + * This is selected to be longer than recommended `kMaxKeyLength` to handle cases where longer keys are used. + * + */ + static constexpr uint8_t kMaxIterKeyLength = OT_DNS_TXT_KEY_ITER_MAX_LENGTH; + /** * Represents an iterator for TXT record entries (key/value pairs). * @@ -1083,9 +1091,9 @@ public: * The `Iterator` instance MUST be initialized using `Init()` before calling this method and the TXT data * buffer used to initialize the iterator MUST persist and remain unchanged. * - * If the parsed key string length is smaller than or equal to `kMaxKeyLength` (recommended max key length) - * the key string is returned in `mKey` in @p aEntry. But if the key is longer, then `mKey` is set to NULL and - * the entire encoded TXT entry is returned in `mValue` and `mValueLength`. + * If the parsed key string length is smaller than or equal to `kMaxIterKeyLength` the key string is returned + * in `mKey` in @p aEntry. But if the key is longer, then `mKey` is set to `nullptr` the entire encoded TXT + * entry is returned in `mValue` and `mValueLength`. * * @param[out] aEntry A reference to a `TxtEntry` to output the parsed/read entry. * diff --git a/src/core/radio/trel_interface.cpp b/src/core/radio/trel_interface.cpp index acbe3e5e7..d25347733 100644 --- a/src/core/radio/trel_interface.cpp +++ b/src/core/radio/trel_interface.cpp @@ -263,7 +263,7 @@ Error Interface::ParsePeerInfoTxtData(const Peer::Info &aInfo, while ((error = iterator.GetNextEntry(entry)) == kErrorNone) { // If the TXT data happens to have entries with key longer - // than `kMaxKeyLength`, `mKey` would be `nullptr` and full + // than `kMaxIterKeyLength`, `mKey` would be `nullptr` and full // entry would be placed in `mValue`. We skip over such // entries. if (entry.mKey == nullptr) diff --git a/tests/unit/test_dns.cpp b/tests/unit/test_dns.cpp index 8e8d6a0fc..a8408aad4 100644 --- a/tests/unit/test_dns.cpp +++ b/tests/unit/test_dns.cpp @@ -1302,6 +1302,9 @@ void TestDnsTxtEntry(void) const char kKey6[] = "boolKey"; // Should be encoded as "boolKey" (without `=`). const char kKey7[] = "emptyKey"; // Should be encoded as "emptyKey=". + const char kKey8[] = "1234567890123456789012345678901234567890123456789012345678901234567890"; + const uint8_t kValue8[] = "abcd"; + // Invalid key const char kShortKey[] = ""; @@ -1312,6 +1315,17 @@ void TestDnsTxtEntry(void) const uint8_t kEncodedTxt5[] = {12, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '=', 'a'}; const uint8_t kEncodedTxt6[] = {7, 'b', 'o', 'o', 'l', 'K', 'e', 'y'}; const uint8_t kEncodedTxt7[] = {9, 'e', 'm', 'p', 't', 'y', 'K', 'e', 'y', '='}; + const uint8_t kEncodedTxt8[] = { + 75, // length + '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', // 10 + '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', // 20 + '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', // 30 + '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', // 40 + '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', // 50 + '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', // 60 + '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', // 70 + '=', 'a', 'b', 'c', 'd', + }; const uint8_t kInvalidEncodedTxt1[] = {4, 'a', '=', 'b'}; // Incorrect length @@ -1327,6 +1341,7 @@ void TestDnsTxtEntry(void) Dns::TxtEntry(kKey5, kValue5, sizeof(kValue5)), Dns::TxtEntry(kKey6, nullptr, 0), Dns::TxtEntry(kKey7, kValue1, 0), + Dns::TxtEntry(kKey8, kValue8, sizeof(kValue8)), }; const EncodedTxtData kEncodedTxtData[] = { @@ -1381,7 +1396,7 @@ void TestDnsTxtEntry(void) SuccessOrQuit(iterator.GetNextEntry(txtEntry), "TxtEntry::GetNextEntry() failed"); printf("key:\"%s\" valueLen:%d\n", txtEntry.mKey != nullptr ? txtEntry.mKey : "(null)", txtEntry.mValueLength); - if (expectedKeyLength > Dns::TxtEntry::kMaxKeyLength) + if (expectedKeyLength > Dns::TxtEntry::kMaxIterKeyLength) { // When the key is longer than recommended max key length, // the full encoded string is returned in `mValue` and