[dns] check for null character in read label (#13187)

This commit updates `Name::LabelIterator::ReadLabel()` to explicitly
check that the read label from the message does not contain any embedded
`kNullChar` (`\0`) characters. It uses `StringLength()` to verify that
the length of the string matches the expected label length. If a null
character is found before the end of the label, `kErrorParse` is
returned to prevent potential string truncation issues or
misinterpretation of the label name.

This broader check replaces a recent fix in `PtrRecord::ReadPtrName()`
from #13183 which only verified that the first label was not empty
or malformed by checking for a single-character label with a null
byte. By enforcing this validation centrally at the `ReadLabel()`
level, we now ensure that labels of any length are properly
protected against embedded null characters across all DNS record
types.
This commit is contained in:
Abtin Keshavarzian
2026-06-03 14:55:20 -07:00
committed by GitHub
parent 15e1c233bf
commit b2093f4f9e
2 changed files with 27 additions and 4 deletions
+3 -4
View File
@@ -639,6 +639,9 @@ Error Name::LabelIterator::ReadLabel(char *aLabelBuffer, uint8_t &aLabelLength,
aLabelBuffer[mLabelLength] = kNullChar;
aLabelLength = mLabelLength;
// Check that there is no `kNullChar` (`\0`) in the read label.
VerifyOrExit(StringLength(aLabelBuffer, mLabelLength) == mLabelLength, error = kErrorParse);
if (!aAllowDotCharInLabel)
{
VerifyOrExit(StringFind(aLabelBuffer, kLabelSeparatorChar) == nullptr, error = kErrorParse);
@@ -1592,10 +1595,6 @@ Error PtrRecord::ReadPtrName(const Message &aMessage,
aOffset = startOffset + sizeof(PtrRecord);
SuccessOrExit(error = Name::ReadLabel(aMessage, aOffset, aLabelBuffer, aLabelBufferSize));
// The first label of a PTR target (the service-instance or host label)
// must be non-empty.
VerifyOrExit(aLabelBuffer[0] != kNullChar, error = kErrorParse);
if (aNameBuffer != nullptr)
{
SuccessOrExit(error = Name::ReadName(aMessage, aOffset, aNameBuffer, aNameBufferSize));
+24
View File
@@ -161,6 +161,14 @@ void TestDnsName(void)
{"_s1._sub._srv._udp.default.service.arpa.", "_s1", "_sub._srv._udp", "default.service.arpa.", true},
};
typedef uint8_t EncodedNameWithNullChar[6];
static const EncodedNameWithNullChar kEncodedNamesWithNullChar[] = {
{4, 0, 'a', 'b', 'c', 0}, // Null char at the start of the label
{4, 'a', 0, 'c', 'd', 0}, // Null char in the middle of the label
{4, 'a', 'b', 'c', 0, 0} // Null char in the end of the label
};
printf("================================================================\n");
printf("TestDnsName()\n");
@@ -626,6 +634,22 @@ void TestDnsName(void)
"012345678901234567890123456789012345678901234567890123456789012") ==
kErrorInvalidArgs);
printf("----------------------------------------------------------------\n");
printf("Name::ReadLabel() when there is null-char \'\\0\' in the label\n");
for (const EncodedNameWithNullChar &encodedName : kEncodedNamesWithNullChar)
{
SuccessOrQuit(message->SetLength(0));
SuccessOrQuit(message->AppendBytes(encodedName, sizeof(encodedName)));
SuccessOrQuit(message->Read(0, buffer, message->GetLength()));
DumpBuffer("EncodedName", buffer, message->GetLength());
offset = 0;
labelLength = sizeof(label);
VerifyOrQuit(Dns::Name::ReadLabel(*message, offset, label, labelLength) == kErrorParse);
}
message->Free();
testFreeInstance(instance);
}