Commit message: evdns: name_parse(): fix remote stack overread

@asn-the-goblin-slayer:
  "the name_parse() function in libevent's DNS code is vulnerable to a buffer overread.

   971         if (cp != name_out) {
   972             if (cp + 1 >= end) return -1;
   973             *cp++ = '.';
   974         }
   975         if (cp + label_len >= end) return -1;
   976         memcpy(cp, packet + j, label_len);
   977         cp += label_len;
   978         j += label_len;
   No check is made against length before the memcpy occurs.

   This was found through the Tor bug bounty program and the discovery should be credited to 'Guido Vranken'."

Reproducer for gdb (https://gist.github.com/azat/e4fcf540e9b89ab86d02):
  set $PROT_NONE=0x0
  set $PROT_READ=0x1
  set $PROT_WRITE=0x2
  set $MAP_ANONYMOUS=0x20
  set $MAP_SHARED=0x01
  set $MAP_FIXED=0x10
  set $MAP_32BIT=0x40

  start

  set $length=202
  # overread
  set $length=2
  # allocate with mmap to have a seg fault on page boundary
  set $l=(1<<20)*2
  p mmap(0, $l, $PROT_READ|$PROT_WRITE, $MAP_ANONYMOUS|$MAP_SHARED|$MAP_32BIT, -1, 0)
  set $packet=(char *)$1+$l-$length
  # hack the packet
  set $packet[0]=63
  set $packet[1]='/'

  p malloc(sizeof(int))
  set $idx=(int *)$2
  set $idx[0]=0
  set $name_out_len=202

  p malloc($name_out_len)
  set $name_out=$3

  # have WRITE only mapping to fail on read
  set $end=$1+$l
  p (void *)mmap($end, 1<<12, $PROT_NONE, $MAP_ANONYMOUS|$MAP_SHARED|$MAP_FIXED|$MAP_32BIT, -1, 0)
  set $m=$4

  p name_parse($packet, $length, $idx, $name_out, $name_out_len)
  x/2s (char *)$name_out

Before this patch:
$ gdb -ex 'source gdb' dns-example
$1 = 1073741824
$2 = (void *) 0x633010
$3 = (void *) 0x633030
$4 = (void *) 0x40200000

Program received signal SIGSEGV, Segmentation fault.
__memcpy_sse2_unaligned () at memcpy-sse2-unaligned.S:33

After this patch:
$ gdb -ex 'source gdb' dns-example
$1 = 1073741824
$2 = (void *) 0x633010
$3 = (void *) 0x633030
$4 = (void *) 0x40200000
$5 = -1
0x633030:       "/"
0x633032:       ""
(gdb) p $m
$6 = (void *) 0x40200000
(gdb) p $1
$7 = 1073741824
(gdb) p/x $1
$8 = 0x40000000
(gdb) quit

P.S. plus drop one condition duplicate.

Fixes: #317
CVE: CVE-2016-10195
CWE: CWE-125
Vulnerability description: The name_parse function in evdns.c in libevent before 2.1.6-beta allows remote attackers to have unspecified impact via vectors involving the label_len variable, which triggers an out-of-bounds stack read.

Project: libevent

name_parse(u8 *packet, int length, int *idx, char *name_out, int name_out_len) {
	int name_end = -1;
	int j = *idx;
	int ptr_count = 0;
#define GET32(x) do { if (j + 4 > length) goto err; memcpy(&t32_, packet + j, 4); j += 4; x = ntohl(t32_); } while (0)
#define GET16(x) do { if (j + 2 > length) goto err; memcpy(&t_, packet + j, 2); j += 2; x = ntohs(t_); } while (0)
#define GET8(x) do { if (j >= length) goto err; x = packet[j++]; } while (0)

	char *cp = name_out;
	const char *const end = name_out + name_out_len;

	/* Normally, names are a series of length prefixed strings terminated */
	/* with a length of 0 (the lengths are u8's < 63). */
	/* However, the length can start with a pair of 1 bits and that */
	/* means that the next 14 bits are a pointer within the current */
	/* packet. */
 
 	for (;;) {
 		u8 label_len;
		if (j >= length) return -1;
 		GET8(label_len);
 		if (!label_len) break;
 		if (label_len & 0xc0) {
			u8 ptr_low;
			GET8(ptr_low);
			if (name_end < 0) name_end = j;
			j = (((int)label_len & 0x3f) << 8) + ptr_low;
			/* Make sure that the target offset is in-bounds. */
			if (j < 0 || j >= length) return -1;
			/* If we've jumped more times than there are characters in the
			 * message, we must have a loop. */
			if (++ptr_count > length) return -1;
			continue;
		}
		if (label_len > 63) return -1;
		if (cp != name_out) {
			if (cp + 1 >= end) return -1;
 			*cp++ = '.';
 		}
 		if (cp + label_len >= end) return -1;
 		memcpy(cp, packet + j, label_len);
 		cp += label_len;
 		j += label_len;
	}
	if (cp >= end) return -1;
	*cp = '\0';
	if (name_end < 0)
		*idx = j;
	else
		*idx = name_end;
	return 0;
 err:
	return -1;
}