From: Colin Vidal Date: Wed, 3 Jun 2026 14:08:57 +0000 (+0200) Subject: Do not assert on synthrecord reverse mode with huge prefix X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=8bd2f2c0eff7c5afc36398d05841f2643f4f9c8d;p=thirdparty%2Fbind9.git Do not assert on synthrecord reverse mode with huge prefix When using the `synthrecord` plugin in reverse mode, if a very long prefix is configured by the operator such that there is no room to fit the reversed IP address into a DNS name, `named` could assert. This has now been fixed. In such situations, an error is logged so the operator is aware of the problem, and `NXDOMAIN` is answered. --- diff --git a/bin/plugins/synthrecord.c b/bin/plugins/synthrecord.c index 4f7bff17b40..f586d3f9e07 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)