diff -Naur dnsmasq-2.76.orig/src/dnsmasq.h dnsmasq-2.76/src/dnsmasq.h
--- dnsmasq-2.76.orig/src/dnsmasq.h	2016-05-18 07:51:54.000000000 -0700
+++ dnsmasq-2.76/src/dnsmasq.h	2017-09-26 11:46:52.543096582 -0700
@@ -1161,7 +1161,7 @@
 u64 rand64(void);
 int legal_hostname(char *c);
 char *canonicalise(char *s, int *nomem);
-unsigned char *do_rfc1035_name(unsigned char *p, char *sval);
+unsigned char *do_rfc1035_name(unsigned char *p, char *sval, char *limit);
 void *safe_malloc(size_t size);
 void safe_pipe(int *fd, int read_noblock);
 void *whine_malloc(size_t size);
diff -Naur dnsmasq-2.76.orig/src/dnssec.c dnsmasq-2.76/src/dnssec.c
--- dnsmasq-2.76.orig/src/dnssec.c	2016-05-18 07:51:54.000000000 -0700
+++ dnsmasq-2.76/src/dnssec.c	2017-09-26 11:46:12.100665576 -0700
@@ -2227,7 +2227,7 @@
 
   p = (unsigned char *)(header+1);
 	
-  p = do_rfc1035_name(p, name);
+  p = do_rfc1035_name(p, name, NULL);
   *p++ = 0;
   PUTSHORT(type, p);
   PUTSHORT(class, p);
diff -Naur dnsmasq-2.76.orig/src/edns0.c dnsmasq-2.76/src/edns0.c
--- dnsmasq-2.76.orig/src/edns0.c	2016-05-18 07:51:54.000000000 -0700
+++ dnsmasq-2.76/src/edns0.c	2017-09-26 11:46:12.100665576 -0700
@@ -144,7 +144,7 @@
 	  GETSHORT(len, p);
 	  
 	  /* malformed option, delete the whole OPT RR and start again. */
-	  if (i + len > rdlen)
+	  if (i + 4 + len > rdlen)
 	    {
 	      rdlen = 0;
 	      is_last = 0;
@@ -159,7 +159,7 @@
 	      /* delete option if we're to replace it. */
 	      p -= 4;
 	      rdlen -= len + 4;
-	      memcpy(p, p+len+4, rdlen - i);
+	      memmove(p, p+len+4, rdlen - i);
 	      PUTSHORT(rdlen, lenp);
 	      lenp -= 2;
 	    }
@@ -192,7 +192,15 @@
 	  !(p = skip_section(p, 
 			     ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount), 
 			     header, plen)))
+      {
+	free(buff);
 	return plen;
+      }
+      if (p + 11 > limit)
+      {
+        free(buff);
+        return plen; /* Too big */
+      }
       *p++ = 0; /* empty name */
       PUTSHORT(T_OPT, p);
       PUTSHORT(udp_sz, p); /* max packet length, 512 if not given in EDNS0 header */
@@ -204,6 +212,11 @@
       /* Copy back any options */
       if (buff)
 	{
+          if (p + rdlen > limit)
+          {
+            free(buff);
+            return plen; /* Too big */
+          }
 	  memcpy(p, buff, rdlen);
 	  free(buff);
 	  p += rdlen;
@@ -217,8 +230,12 @@
   /* Add new option */
   if (optno != 0 && replace != 2)
     {
+      if (p + 4 > limit)
+       return plen; /* Too big */
       PUTSHORT(optno, p);
       PUTSHORT(optlen, p);
+      if (p + optlen > limit)
+       return plen; /* Too big */
       memcpy(p, opt, optlen);
       p += optlen;  
       PUTSHORT(p - datap, lenp);
diff -Naur dnsmasq-2.76.orig/src/forward.c dnsmasq-2.76/src/forward.c
--- dnsmasq-2.76.orig/src/forward.c	2016-05-18 07:51:54.000000000 -0700
+++ dnsmasq-2.76/src/forward.c	2017-09-26 11:46:12.100665576 -0700
@@ -1410,6 +1410,10 @@
 	udp_size = daemon->edns_pktsz;
     }
 
+  // Make sure the udp size is not smaller than the incoming message so that we
+  // do not underflow
+  if (udp_size < n) udp_size = n;
+
 #ifdef HAVE_AUTH
   if (auth_dns)
     {
diff -Naur dnsmasq-2.76.orig/src/option.c dnsmasq-2.76/src/option.c
--- dnsmasq-2.76.orig/src/option.c	2016-05-18 07:51:54.000000000 -0700
+++ dnsmasq-2.76/src/option.c	2017-09-26 11:46:12.100665576 -0700
@@ -1378,7 +1378,7 @@
 		    }
 		  
 		  p = newp;
-		  end = do_rfc1035_name(p + len, dom);
+		  end = do_rfc1035_name(p + len, dom, NULL);
 		  *end++ = 0;
 		  len = end - p;
 		  free(dom);
diff -Naur dnsmasq-2.76.orig/src/radv.c dnsmasq-2.76/src/radv.c
--- dnsmasq-2.76.orig/src/radv.c	2016-05-18 07:51:54.000000000 -0700
+++ dnsmasq-2.76/src/radv.c	2017-09-26 11:46:12.104665422 -0700
@@ -198,6 +198,9 @@
       /* look for link-layer address option for logging */
       if (sz >= 16 && packet[8] == ICMP6_OPT_SOURCE_MAC && (packet[9] * 8) + 8 <= sz)
 	{
+	  if ((packet[9] * 8 - 2) * 3 - 1 >= MAXDNAME) {
+	    return;
+	  }
 	  print_mac(daemon->namebuff, &packet[10], (packet[9] * 8) - 2);
 	  mac = daemon->namebuff;
 	}
diff -Naur dnsmasq-2.76.orig/src/rfc1035.c dnsmasq-2.76/src/rfc1035.c
--- dnsmasq-2.76.orig/src/rfc1035.c	2016-05-18 07:51:54.000000000 -0700
+++ dnsmasq-2.76/src/rfc1035.c	2017-09-26 12:22:20.445298619 -0700
@@ -37,7 +37,7 @@
 	/* end marker */
 	{
 	  /* check that there are the correct no of bytes after the name */
-	  if (!CHECK_LEN(header, p, plen, extrabytes))
+	  if (!CHECK_LEN(header, p1 ? p1 : p, plen, extrabytes))
 	    return 0;
 	  
 	  if (isExtract)
@@ -485,6 +485,8 @@
 	    {
 	      unsigned int i, len = *p1;
 	      unsigned char *p2 = p1;
+	      if ((p1 + len - p) >= rdlen)
+	        return 0; /* bad packet */
 	      /* make counted string zero-term  and sanitise */
 	      for (i = 0; i < len; i++)
 		{
@@ -1058,12 +1060,21 @@
   unsigned short usval;
   long lval;
   char *sval;
+#define CHECK_LIMIT(size) \
+  if (limit && p + (size) > (unsigned char*)limit) \
+    { \
+      va_end(ap); \
+      goto truncated; \
+    }
 
   if (truncp && *truncp)
     return 0;
- 
+
   va_start(ap, format);   /* make ap point to 1st unamed argument */
-  
+
+  /* nameoffset (1 or 2) + type (2) + class (2) + ttl (4) + 0 (2) */
+  CHECK_LIMIT(12);
+
   if (nameoffset > 0)
     {
       PUTSHORT(nameoffset | 0xc000, p);
@@ -1072,7 +1083,13 @@
     {
       char *name = va_arg(ap, char *);
       if (name)
-	p = do_rfc1035_name(p, name);
+	p = do_rfc1035_name(p, name, limit);
+        if (!p)
+          {
+            va_end(ap);
+            goto truncated;
+          }
+
       if (nameoffset < 0)
 	{
 	  PUTSHORT(-nameoffset | 0xc000, p);
@@ -1093,6 +1110,7 @@
       {
 #ifdef HAVE_IPV6
       case '6':
+        CHECK_LIMIT(IN6ADDRSZ);
 	sval = va_arg(ap, char *); 
 	memcpy(p, sval, IN6ADDRSZ);
 	p += IN6ADDRSZ;
@@ -1100,36 +1118,47 @@
 #endif
 	
       case '4':
+        CHECK_LIMIT(INADDRSZ);
 	sval = va_arg(ap, char *); 
 	memcpy(p, sval, INADDRSZ);
 	p += INADDRSZ;
 	break;
 	
       case 'b':
+        CHECK_LIMIT(1);
 	usval = va_arg(ap, int);
 	*p++ = usval;
 	break;
 	
       case 's':
+        CHECK_LIMIT(2);
 	usval = va_arg(ap, int);
 	PUTSHORT(usval, p);
 	break;
 	
       case 'l':
+        CHECK_LIMIT(4);
 	lval = va_arg(ap, long);
 	PUTLONG(lval, p);
 	break;
 	
       case 'd':
-	/* get domain-name answer arg and store it in RDATA field */
-	if (offset)
-	  *offset = p - (unsigned char *)header;
-	p = do_rfc1035_name(p, va_arg(ap, char *));
-	*p++ = 0;
+        /* get domain-name answer arg and store it in RDATA field */
+        if (offset)
+          *offset = p - (unsigned char *)header;
+        p = do_rfc1035_name(p, va_arg(ap, char *), limit);
+        if (!p)
+          {
+            va_end(ap);
+            goto truncated;
+          }
+        CHECK_LIMIT(1);
+        *p++ = 0;
 	break;
 	
       case 't':
 	usval = va_arg(ap, int);
+        CHECK_LIMIT(usval);
 	sval = va_arg(ap, char *);
 	if (usval != 0)
 	  memcpy(p, sval, usval);
@@ -1141,20 +1170,24 @@
 	usval = sval ? strlen(sval) : 0;
 	if (usval > 255)
 	  usval = 255;
+        CHECK_LIMIT(usval + 1);
 	*p++ = (unsigned char)usval;
 	memcpy(p, sval, usval);
 	p += usval;
 	break;
       }
 
+#undef CHECK_LIMIT
   va_end(ap);	/* clean up variable argument pointer */
   
   j = p - sav - 2;
-  PUTSHORT(j, sav);     /* Now, store real RDLength */
+ /* this has already been checked against limit before */
+ PUTSHORT(j, sav);     /* Now, store real RDLength */
   
   /* check for overflow of buffer */
   if (limit && ((unsigned char *)limit - p) < 0)
     {
+truncated:
       if (truncp)
 	*truncp = 1;
       return 0;
diff -Naur dnsmasq-2.76.orig/src/rfc2131.c dnsmasq-2.76/src/rfc2131.c
--- dnsmasq-2.76.orig/src/rfc2131.c	2016-05-18 07:51:54.000000000 -0700
+++ dnsmasq-2.76/src/rfc2131.c	2017-09-26 11:46:12.112665112 -0700
@@ -155,7 +155,7 @@
 	  for (offset = 0; offset < (len - 5); offset += elen + 5)
 	    {
 	      elen = option_uint(opt, offset + 4 , 1);
-	      if (option_uint(opt, offset, 4) == BRDBAND_FORUM_IANA)
+	      if (option_uint(opt, offset, 4) == BRDBAND_FORUM_IANA && offset + elen + 5 <= len)
 		{
 		  unsigned char *x = option_ptr(opt, offset + 5);
 		  unsigned char *y = option_ptr(opt, offset + elen + 5);
@@ -2419,10 +2419,10 @@
 
 	      if (fqdn_flags & 0x04)
 		{
-		  p = do_rfc1035_name(p, hostname);
+		  p = do_rfc1035_name(p, hostname, NULL);
 		  if (domain)
 		    {
-		      p = do_rfc1035_name(p, domain);
+		      p = do_rfc1035_name(p, domain, NULL);
 		      *p++ = 0;
 		    }
 		}
diff -Naur dnsmasq-2.76.orig/src/rfc3315.c dnsmasq-2.76/src/rfc3315.c
--- dnsmasq-2.76.orig/src/rfc3315.c	2016-05-18 07:51:54.000000000 -0700
+++ dnsmasq-2.76/src/rfc3315.c	2017-09-26 11:46:12.112665112 -0700
@@ -206,6 +206,9 @@
   /* RFC-6939 */
   if ((opt = opt6_find(opts, end, OPTION6_CLIENT_MAC, 3)))
     {
+      if (opt6_len(opt) - 2 > DHCP_CHADDR_MAX) {
+        return 0;
+      }
       state->mac_type = opt6_uint(opt, 0, 2);
       state->mac_len = opt6_len(opt) - 2;
       memcpy(&state->mac[0], opt6_ptr(opt, 2), state->mac_len);
@@ -213,6 +216,9 @@
   
   for (opt = opts; opt; opt = opt6_next(opt, end))
     {
+      if (opt6_ptr(opt, 0) + opt6_len(opt) >= end) {
+        return 0;
+      }
       int o = new_opt6(opt6_type(opt));
       if (opt6_type(opt) == OPTION6_RELAY_MSG)
 	{
@@ -1472,10 +1478,10 @@
       if ((p = expand(len + 2)))
 	{
 	  *(p++) = state->fqdn_flags;
-	  p = do_rfc1035_name(p, state->hostname);
+	  p = do_rfc1035_name(p, state->hostname, NULL);
 	  if (state->send_domain)
 	    {
-	      p = do_rfc1035_name(p, state->send_domain);
+	      p = do_rfc1035_name(p, state->send_domain, NULL);
 	      *p = 0;
 	    }
 	}
diff -Naur dnsmasq-2.76.orig/src/util.c dnsmasq-2.76/src/util.c
--- dnsmasq-2.76.orig/src/util.c	2016-05-18 07:51:54.000000000 -0700
+++ dnsmasq-2.76/src/util.c	2017-09-26 11:46:12.112665112 -0700
@@ -218,15 +218,20 @@
   return ret;
 }
 
-unsigned char *do_rfc1035_name(unsigned char *p, char *sval)
+unsigned char *do_rfc1035_name(unsigned char *p, char *sval, char *limit)
 {
   int j;
   
   while (sval && *sval)
     {
+      if (limit && p + 1 > (unsigned char*)limit)
+        return p;
+
       unsigned char *cp = p++;
       for (j = 0; *sval && (*sval != '.'); sval++, j++)
 	{
+          if (limit && p + 1 > (unsigned char*)limit)
+            return p;
 #ifdef HAVE_DNSSEC
 	  if (option_bool(OPT_DNSSEC_VALID) && *sval == NAME_ESCAPE)
 	    *p++ = (*(++sval))-1;