diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index 4c0af64d64..145f9c9306 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -288,16 +288,33 @@ append(const char *text, size_t len, char **p, char *end) { static isc_result_t reverse_octets(const char *in, char **p, char *end) { - const char *dot = strchr(in, '.'); - size_t len; - if (dot != NULL) { - RETERR(reverse_octets(dot + 1, p, end)); - RETERR(append(".", 1, p, end)); - len = (int)(dot - in); - } else { - len = (int)strlen(in); + const char *parts[DNS_NAME_MAXLABELS]; + size_t lens[DNS_NAME_MAXLABELS]; + size_t n = 0; + const char *cursor = in; + + while (true) { + const char *dot = strchr(cursor, '.'); + if (n >= DNS_NAME_MAXLABELS) { + return DNS_R_NAMETOOLONG; + } + parts[n] = cursor; + lens[n] = (dot != NULL) ? (size_t)(dot - cursor) + : strlen(cursor); + n++; + if (dot == NULL) { + break; + } + cursor = dot + 1; } - return append(in, len, p, end); + + for (size_t i = n; i-- > 0;) { + if (i + 1 < n) { + RETERR(append(".", 1, p, end)); + } + RETERR(append(parts[i], lens[i], p, end)); + } + return ISC_R_SUCCESS; } isc_result_t diff --git a/bin/tests/system/digdelv/tests.sh b/bin/tests/system/digdelv/tests.sh index 977812ab00..7cccfeb73a 100644 --- a/bin/tests/system/digdelv/tests.sh +++ b/bin/tests/system/digdelv/tests.sh @@ -148,6 +148,20 @@ if [ -x "$DIG" ]; then if [ $ret -ne 0 ]; then echo_i "failed"; fi status=$((status + ret)) + n=$((n + 1)) + echo_i "checking dig -x rejects deeply nested input cleanly ($n)" + ret=0 + longinput="$(printf '1.%.0s' $(seq 1 6400))1" + # Pre-fix: SIGSEGV (139) or ASan abort (134) from unbounded recursion in + # reverse_octets() on the dots. Post-fix: structured rejection via + # DNS_R_NAMETOOLONG -> "Invalid IP address" -> exit 1. + rc=0 + dig_with_opts -x "$longinput" >dig.out.test$n 2>&1 || rc=$? + [ $rc -ge 128 ] && ret=1 + grep "Invalid IP address" dig.out.test$n >/dev/null || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + n=$((n + 1)) echo_i "checking dig over TCP works ($n)" ret=0