Infinite loop via GENERATE
In lib/dns/master.c, function genname(), it and delta are both of type int. There is an issue when delta is negative (which nothing prevents) when calling nibbles(). The implemented check does not create an error, since a negative value is always smaller than "INT_MAX - it" for a positive value of it.
/*
* 'it' is >= 0 so we don't need to check for
* underflow.
*/
if ((it > 0 && delta > INT_MAX - it)) {
return (ISC_R_RANGE);
}
if (nibblemode) {
n = nibbles(numbuf, sizeof(numbuf), width,
mode[0], it + delta);
} else {
n = snprintf(numbuf, sizeof(numbuf), fmt,
it + delta);
}
In nibbles(), the right shift of value will sign extend, and value will never reach 0, which causes an infinite loop.
static unsigned int
nibbles(char *numbuf, size_t length, unsigned int width, char mode, int value) {
unsigned int count = 0;
/*
* This reserve space for the NUL string terminator.
*/
if (length > 0U) {
*numbuf = '\0';
length--;
}
do {
char val = hex[(value & 0x0f) + ((mode == 'n') ? 0 : 16)];
value >>= 4;
if (length > 0U) {
*numbuf++ = val;
*numbuf = '\0';
length--;
}
if (width > 0) {
width--;
}
count++;
/*
* If width is non zero then we need to add a label separator.
* If value is non zero then we need to add another label and
* that requires a label separator.
*/
if (width > 0 || value != 0) {
if (length > 0U) {
*numbuf++ = '.';
*numbuf = '\0';
length--;
}
if (width > 0) {
width--;
}
count++;
}
} while (value != 0 || width > 0);
return (count);
}
Since GENERATE is only allowed in trusted zone files, it should not be possible to trigger this for an attacker.
Converting value to unsigned int fixes this issue.