diff --git a/pdns/lua-record.cc b/pdns/lua-record.cc index 1cb8355b4611..452363439c64 100644 --- a/pdns/lua-record.cc +++ b/pdns/lua-record.cc @@ -1132,6 +1132,16 @@ static void setupLuaRecords(LuaContext& lua) // NOLINT(readability-function-cogn string dashed=ip6.toString(); boost::replace_all(dashed, ":", "-"); + // https://github.com/PowerDNS/pdns/issues/7524 + if (boost::ends_with(dashed, "-")) { + // "a--a-" -> "a--a-0" + dashed.push_back('0'); + } + if (boost::starts_with(dashed, "-") || dashed.compare(2, 2, "--") == 0) { + // "-a--a" -> "0-a--a" "aa--a" -> "0aa--a" + dashed.insert(0, "0"); + } + for(int i=31; i>=0; --i) fmt % labels[i]; fmt % dashed; diff --git a/regression-tests.auth-py/test_LuaRecords.py b/regression-tests.auth-py/test_LuaRecords.py index 213f1767dfab..6e08b957d4d5 100644 --- a/regression-tests.auth-py/test_LuaRecords.py +++ b/regression-tests.auth-py/test_LuaRecords.py @@ -162,6 +162,7 @@ class BaseLuaTest(AuthTest): *.createforward IN LUA A "filterForward(createForward(), newNMG{{'1.0.0.0/8', '64.0.0.0/8'}})" *.createforward6 IN LUA AAAA "filterForward(createForward6(), newNMG{{'2000::/3'}}, 'fe80::1')" +*.no-filter.createforward6 IN LUA AAAA "createForward6()" *.createreverse IN LUA PTR "createReverse('%5%.example.com', {{['10.10.10.10'] = 'quad10.example.com.'}})" *.createreverse6 IN LUA PTR "createReverse6('%33%.example.com', {{['2001:db8::1'] = 'example.example.com.'}})" @@ -1075,6 +1076,46 @@ def testCreateForwardAndReverse(self): self.assertRcodeEqual(res, dns.rcode.NOERROR) self.assertEqual(res.answer, response.answer) + def testCreateForwardAndReverseWithZero(self): + """ + Fix #7524 + """ + expected = { + ".no-filter.createforward6.example.org." : (dns.rdatatype.AAAA, { + "0--0" : "::", + "0--1" : "::1", + "0aa--0" : "aa::", + "0aa--1" : "aa::1", + "2001--0" : "2001::", + "a-b--c" : "a:b::c", + "a--b-c" : "a::b:c" + }), + ".createreverse6.example.org." : (dns.rdatatype.PTR, { + "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0" : "0--0.example.com.", + "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0" : "0--1.example.com.", + "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.a.a.0.0" : "0aa--0.example.com.", + "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.a.a.0.0" : "0aa--1.example.com.", + "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.0.0.2" : "2001--0.example.com.", + "c.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.b.0.0.0.a.0.0.0" : "a-b--c.example.com.", + "c.0.0.0.b.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.a.0.0.0" : "a--b-c.example.com." + }) + } + + for suffix, v in expected.items(): + qtype, pairs = v + for prefix, target in pairs.items(): + name = prefix + suffix + + query = dns.message.make_query(name, qtype) + response = dns.message.make_response(query) + response.answer.append(dns.rrset.from_text( + name, 0, dns.rdataclass.IN, qtype, target)) + + res = self.sendUDPQuery(query) + print(res) + self.assertRcodeEqual(res, dns.rcode.NOERROR) + self.assertEqual(res.answer, response.answer) + def _getCounter(self, tcp=False): """ Helper function for shared/non-shared testing