diff --git a/bin/plugins/synthrecord.c b/bin/plugins/synthrecord.c index 4f7bff17b4..f586d3f9e0 100644 --- a/bin/plugins/synthrecord.c +++ b/bin/plugins/synthrecord.c @@ -67,7 +67,7 @@ synthrecord_reverseanswer(synthrecord_t *inst, isc_netaddr_t *na, REQUIRE(na->family == AF_INET || na->family == AF_INET6); isc_buffer_init(&b, bdata, sizeof(bdata)); - isc_buffer_copyregion(&b, &inst->prefix); + RETERR(isc_buffer_copyregion(&b, &inst->prefix)); isc_buffer_init(&addrb, addrbdata, sizeof(addrbdata)); RETERR(isc_netaddr_totext(na, &addrb)); @@ -86,6 +86,9 @@ synthrecord_reverseanswer(synthrecord_t *inst, isc_netaddr_t *na, */ isc_buffer_peekuint8(&addrb, &c); if (c == ':') { + if (isc_buffer_availablelength(&b) == 0) { + return ISC_R_NOSPACE; + } isc_buffer_putuint8(&b, '0'); } @@ -96,12 +99,15 @@ synthrecord_reverseanswer(synthrecord_t *inst, isc_netaddr_t *na, isc_buffer_forward(&addrb, isc_buffer_usedlength(&addrb) - 1); isc_buffer_peekuint8(&addrb, &c); if (c == ':') { + if (isc_buffer_availablelength(&b) == 0) { + return ISC_R_NOSPACE; + } isc_buffer_putuint8(&addrb, '0'); } } isc_buffer_usedregion(&addrb, &addrr); - isc_buffer_copyregion(&b, &addrr); + RETERR(isc_buffer_copyregion(&b, &addrr)); /* * Do not attempt to replace anything in the prefix @@ -214,6 +220,13 @@ synthrecord_parseforward(synthrecord_t *inst, const dns_name_t *name, isc_buffer_init(&b, bdata, sizeof(bdata)); dns_name_totext(&label, DNS_NAME_OMITFINALDOT, &b); + + /* + * Buffer is `DNS_NAME_FORMATSIZE` which is the maximum length of + * `dns_name_totext()` can put in there, plus one byte which we're + * setting here. So we know there is at least one remaining byte in the + * buffer. + */ isc_buffer_putuint8(&b, 0); if (strncmp((const char *)inst->prefix.base, isc_buffer_base(&b), inst->prefix.length) != 0) diff --git a/bin/tests/system/synthrecord/ns1/named.conf.j2 b/bin/tests/system/synthrecord/ns1/named.conf.j2 index f2421febb1..0193196b1f 100644 --- a/bin/tests/system/synthrecord/ns1/named.conf.j2 +++ b/bin/tests/system/synthrecord/ns1/named.conf.j2 @@ -1,4 +1,5 @@ {% set inview = inview | default(False) %} +{% set toolongprefix = toolongprefix | default(False) %} options { query-source address 10.53.0.1; @@ -56,7 +57,11 @@ zone "0.53.10.in-addr.arpa." { type primary; file "0.53.10.in-addr.arpa.db"; plugin query "@TOP_BUILDDIR@/synthrecord" { +{% if toolongprefix %} + prefix "waytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefixwaytoolongprefix"; +{% else %} prefix "dynamic-"; +{% endif %} allow-synth { 10.53.0.0/24; }; diff --git a/bin/tests/system/synthrecord/tests_synthrecord.py b/bin/tests/system/synthrecord/tests_synthrecord.py index 3579b7a33d..dc66d9fe5f 100644 --- a/bin/tests/system/synthrecord/tests_synthrecord.py +++ b/bin/tests/system/synthrecord/tests_synthrecord.py @@ -508,3 +508,18 @@ def test_synthrecord_inview(ns1, templates): cmd = ns1.rndc("reconfig", raise_on_exception=False) assert cmd.rc != 0 watcher.wait_for_line("'synthrecord' must be configured as a zone plugin") + + +def test_synthrecord_toolongprefix(ns1, templates): + templates.render("ns1/named.conf", {"toolongprefix": True}) + with ns1.watch_log_from_here() as watcher: + ns1.rndc("reconfig") + watcher.wait_for_line("running") + ip = IPv4Address("10.53.0.8") + with ns1.watch_log_from_here() as watcher: + query = dns.message.make_query(ip.reverse_pointer, "PTR") + res = isctest.query.udp(query, SERVER) + assert res.rcode() == dns.rcode.NXDOMAIN + watcher.wait_for_line( + "synthrecord cannot create reverse answer name: ran out of space" + )