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
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