From b4b5aaa31d4fd51097e6afc2fb8eb92a65e7e545 Mon Sep 17 00:00:00 2001 From: Miod Vallat Date: Mon, 8 Sep 2025 15:36:20 +0200 Subject: [PATCH] Allow quoted words to immediately follow non-quoted in text record contents. Also reject \DDD escapes with a value larger than 8 bits. Signed-off-by: Miod Vallat --- pdns/rcpgenerator.cc | 8 +++++++- pdns/test-dnsrecords_cc.cc | 3 ++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/pdns/rcpgenerator.cc b/pdns/rcpgenerator.cc index fee6cc063..3be09a915 100644 --- a/pdns/rcpgenerator.cc +++ b/pdns/rcpgenerator.cc @@ -642,7 +642,7 @@ void RecordTextReader::xfrText(string& val, bool multi, bool /* lenField */) char chr2 = d_string[d_pos + 1]; char chr3 = d_string[d_pos + 2]; if (chr2 >= '0' && chr2 <= '9' && chr3 >= '0' && chr3 <= '9') { - valid = true; + valid = 100 * (chr - '0') + 10 * (chr2 - '0') + chr3 - '0' < 256; } } if (!valid) { @@ -652,6 +652,12 @@ void RecordTextReader::xfrText(string& val, bool multi, bool /* lenField */) // Not advancing d_pos, we'll append the next 1 or 3 characters as // part of the regular case. } + if (!quoted && d_string[d_pos] == '"') { + // Bind allows a non-quoted text to be immediately followed by a + // quoted text, without any whitespace in between, so handle this + // as a delimiter. + break; + } val.append(1, d_string[d_pos]); ++d_pos; } diff --git a/pdns/test-dnsrecords_cc.cc b/pdns/test-dnsrecords_cc.cc index cdb0e6245..321d9a6e8 100644 --- a/pdns/test-dnsrecords_cc.cc +++ b/pdns/test-dnsrecords_cc.cc @@ -100,7 +100,6 @@ BOOST_AUTO_TEST_CASE(test_record_types) { (CASE_S(QType::TXT, "\"\\195\\133LAND ISLANDS\"", "\x0e\xc3\x85LAND ISLANDS")) (CASE_S(QType::TXT, "\"text with DEL in there: \\127\"", "\x19text with DEL in there: \x7f")) (CASE_L(QType::TXT, "\"\xc3\x85LAND ISLANDS\"", "\"\\195\\133LAND ISLANDS\"", "\x0e\xc3\x85LAND ISLANDS")) - (CASE_S(QType::TXT, "\"nonbreakingtxt\"", "\x0enonbreakingtxt")) // local name (CASE_S(QType::RP, "admin.rec.test. admin-info.rec.test.", "\x05""admin\x03rec\x04test\x00\x0a""admin-info\x03rec\x04test\x00")) // non-local name @@ -384,6 +383,8 @@ BOOST_AUTO_TEST_CASE(test_record_types_bad_values) { // non-local overly large name (256), must be broken (ZONE_CASE(QType::CNAME, "123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012.")) (ZONE_CASE(QType::SOA, "ns.rec.test hostmaster.test.rec 20130512010 3600 3600 604800 120")) // too long serial + (ZONE_CASE(QType::TXT, "\\02unlimited")) // incorrect escape + (ZONE_CASE(QType::TXT, "\\384excessive")) // incorrect escape ; int n=0; -- 2.47.3