From 28153eb87a14fd354cf619854f351d2e566c4050 Mon Sep 17 00:00:00 2001
From: Vladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Date: Sun, 20 Oct 2013 17:40:21 +0200
Subject: [PATCH] 	* grub-core/net/arp.c: Remove variable length arrays. 
 * grub-core/net/bootp.c: Likewise. 	* grub-core/net/dns.c: Likewise. 
 * grub-core/net/icmp6.c: Likewise. 	* grub-core/net/net.c: Likewise.

---
 ChangeLog             |  8 ++++
 grub-core/net/arp.c   | 13 +++---
 grub-core/net/bootp.c | 24 +++++++----
 grub-core/net/dns.c   | 15 ++++++-
 grub-core/net/icmp6.c | 13 ++++--
 grub-core/net/net.c   | 98 ++++++++++++++++++++++++++++---------------
 6 files changed, 118 insertions(+), 53 deletions(-)

Index: grub-2.00/grub-core/net/arp.c
===================================================================
--- grub-2.00.orig/grub-core/net/arp.c
+++ grub-2.00/grub-core/net/arp.c
@@ -163,17 +163,20 @@ grub_net_arp_receive (struct grub_net_bu
       {
 	grub_net_link_level_address_t target;
 	/* We've already checked that pln is either 4 or 16.  */
-	char tmp[arp_header->pln];
+	char tmp[16];
+	grub_size_t pln = arp_header->pln;
+
+	if (pln > 16)
+	  pln = 16;
 
 	target.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
 	grub_memcpy (target.mac, sender_hardware_address, 6);
 	grub_memcpy (target_hardware_address, target.mac, 6);
 	grub_memcpy (sender_hardware_address, inf->hwaddress.mac, 6);
 
-	grub_memcpy (tmp, sender_protocol_address, arp_header->pln);
-	grub_memcpy (sender_protocol_address, target_protocol_address,
-		     arp_header->pln);
-	grub_memcpy (target_protocol_address, tmp, arp_header->pln);
+	grub_memcpy (tmp, sender_protocol_address, pln);
+	grub_memcpy (sender_protocol_address, target_protocol_address, pln);
+	grub_memcpy (target_protocol_address, tmp, pln);
 
 	/* Change operation to REPLY and send packet */
 	arp_header->op = grub_be_to_cpu16 (ARP_REPLY);
Index: grub-2.00/grub-core/net/bootp.c
===================================================================
--- grub-2.00.orig/grub-core/net/bootp.c
+++ grub-2.00/grub-core/net/bootp.c
@@ -37,10 +37,11 @@ set_env_limn_ro (const char *intername,
 		 char *value, grub_size_t len)
 {
   char c;
-  char varname[sizeof ("net_") + grub_strlen (intername) + sizeof ("_")
-	       + grub_strlen (suffix)];
+  char *varname;
   char *ptr;
-  grub_snprintf (varname, sizeof (varname), "net_%s_%s", intername, suffix);
+  varname = grub_xasprintf ("net_%s_%s", intername, suffix);
+  if (!varname)
+    return;
   for (ptr = varname; *ptr; ptr++)
     if (*ptr == ':')
       *ptr = '_';    
@@ -50,6 +51,7 @@ set_env_limn_ro (const char *intername,
   value[len] = c;
   grub_register_variable_hook (varname, 0, grub_env_write_readonly);
   grub_env_export (varname);
+  grub_free (varname);
 }
 
 static void
@@ -100,15 +102,17 @@ parse_dhcp_vendor (const char *name, voi
 	    {
 	      grub_net_network_level_netaddress_t target;
 	      grub_net_network_level_address_t gw;
-	      char rname[grub_strlen (name) + sizeof (":default")];
+	      char *rname;
 	      
 	      target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
 	      target.ipv4.base = 0;
 	      target.ipv4.masksize = 0;
 	      gw.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
 	      grub_memcpy (&gw.ipv4, ptr, sizeof (gw.ipv4));
-	      grub_snprintf (rname, sizeof (rname), "%s:default", name);
-	      grub_net_add_route_gw (rname, target, gw);
+	      rname = grub_xasprintf ("%s:default", name);
+	      if (rname)
+		grub_net_add_route_gw (rname, target, gw);
+	      grub_free (rname);
 	    }
 	  break;
 	case GRUB_NET_BOOTP_DNS:
@@ -181,15 +185,17 @@ grub_net_configure_by_dhcp_ack (const ch
     {
       grub_net_network_level_netaddress_t target;
       grub_net_network_level_address_t gw;
-      char rname[grub_strlen (name) + sizeof (":gw")];
+      char *rname;
 	  
       target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
       target.ipv4.base = bp->server_ip;
       target.ipv4.masksize = 32;
       gw.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
       gw.ipv4 = bp->gateway_ip;
-      grub_snprintf (rname, sizeof (rname), "%s:gw", name);
-      grub_net_add_route_gw (rname, target, gw);
+      rname = grub_xasprintf ("%s:gw", name);
+      if (rname)
+	grub_net_add_route_gw (rname, target, gw);
+      grub_free (rname);
 
       target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
       target.ipv4.base = bp->gateway_ip;
Index: grub-2.00/grub-core/net/dns.c
===================================================================
--- grub-2.00.orig/grub-core/net/dns.c
+++ grub-2.00/grub-core/net/dns.c
@@ -421,7 +421,7 @@ grub_net_dns_lookup (const char *name,
   grub_size_t send_servers = 0;
   grub_size_t i, j;
   struct grub_net_buff *nb;
-  grub_net_udp_socket_t sockets[n_servers];
+  grub_net_udp_socket_t *sockets;
   grub_uint8_t *optr;
   const char *iptr;
   struct dns_header *head;
@@ -463,9 +463,16 @@ grub_net_dns_lookup (const char *name,
 	}
     }
 
+  sockets = grub_malloc (sizeof (sockets[0]) * n_servers);
+  if (!sockets)
+    return grub_errno;
+
   data.name = grub_strdup (name);
   if (!data.name)
-    return grub_errno;
+    {
+      grub_free (sockets);
+      return grub_errno;
+    }
 
   nb = grub_netbuff_alloc (GRUB_NET_OUR_MAX_IP_HEADER_SIZE
 			   + GRUB_NET_MAX_LINK_HEADER_SIZE
@@ -475,6 +482,7 @@ grub_net_dns_lookup (const char *name,
 			   + 2 + 4);
   if (!nb)
     {
+      grub_free (sockets);
       grub_free (data.name);
       return grub_errno;
     }
@@ -493,6 +501,7 @@ grub_net_dns_lookup (const char *name,
 	dot = iptr + grub_strlen (iptr);
       if ((dot - iptr) >= 64)
 	{
+	  grub_free (sockets);
 	  grub_free (data.name);
 	  return grub_error (GRUB_ERR_BAD_ARGUMENT,
 			     N_("domain name component is too long"));
@@ -584,6 +593,8 @@ grub_net_dns_lookup (const char *name,
   for (j = 0; j < send_servers; j++)
     grub_net_udp_close (sockets[j]);
   
+  grub_free (sockets);
+
   if (*data.naddresses)
     return GRUB_ERR_NONE;
   if (data.dns_err)
Index: grub-2.00/grub-core/net/icmp6.c
===================================================================
--- grub-2.00.orig/grub-core/net/icmp6.c
+++ grub-2.00/grub-core/net/icmp6.c
@@ -412,14 +412,19 @@ grub_net_recv_icmp6_packet (struct grub_
 		    grub_dprintf ("net", "creating slaac\n");
 
 		    {
-		      char name[grub_strlen (slaac->name)
-				+ sizeof (":XXXXXXXXXXXXXXXXXXXX")];
-		      grub_snprintf (name, sizeof (name), "%s:%d",
-				     slaac->name, slaac->slaac_counter++);
+		      char *name;
+		      name = grub_xasprintf ("%s:%d",
+					     slaac->name, slaac->slaac_counter++);
+		      if (!name)
+			{
+			  grub_errno = GRUB_ERR_NONE;
+			  continue;
+			}
 		      inf = grub_net_add_addr (name, 
 					       card, &addr,
 					       &slaac->address, 0);
 		      grub_net_add_route (name, netaddr, inf);
+		      grub_free (name);
 		    }
 		  }
 	      }
Index: grub-2.00/grub-core/net/net.c
===================================================================
--- grub-2.00.orig/grub-core/net/net.c
+++ grub-2.00/grub-core/net/net.c
@@ -243,17 +243,68 @@ grub_net_ipv6_get_slaac (struct grub_net
   return slaac;
 }
 
+static void
+grub_net_network_level_interface_register (struct grub_net_network_level_interface *inter);
+
+static struct grub_net_network_level_interface *
+grub_net_add_addr_real (char *name,
+			struct grub_net_card *card,
+			const grub_net_network_level_address_t *addr,
+			const grub_net_link_level_address_t *hwaddress,
+			grub_net_interface_flags_t flags)
+{
+  struct grub_net_network_level_interface *inter;
+
+  inter = grub_zalloc (sizeof (*inter));
+  if (!inter)
+    return NULL;
+
+  inter->name = name;
+  grub_memcpy (&(inter->address), addr, sizeof (inter->address));
+  grub_memcpy (&(inter->hwaddress), hwaddress, sizeof (inter->hwaddress));
+  inter->flags = flags;
+  inter->card = card;
+  inter->dhcp_ack = NULL;
+  inter->dhcp_acklen = 0;
+
+  grub_net_network_level_interface_register (inter);
+
+  return inter;
+}
+
+struct grub_net_network_level_interface *
+grub_net_add_addr (const char *name,
+		   struct grub_net_card *card,
+		   const grub_net_network_level_address_t *addr,
+		   const grub_net_link_level_address_t *hwaddress,
+		   grub_net_interface_flags_t flags)
+{
+  char *name_dup = grub_strdup (name);
+  struct grub_net_network_level_interface *ret;
+
+  if (!name_dup)
+    return NULL;
+  ret = grub_net_add_addr_real (name_dup, card, addr, hwaddress, flags);
+  if (!ret)
+    grub_free (name_dup);
+  return ret;
+}
+
 struct grub_net_network_level_interface *
 grub_net_ipv6_get_link_local (struct grub_net_card *card,
 			      const grub_net_link_level_address_t *hwaddr)
 {
   struct grub_net_network_level_interface *inf;
-  char name[grub_strlen (card->name)
-	    + GRUB_NET_MAX_STR_HWADDR_LEN
-	    + sizeof (":link")];
+  char *name;
   char *ptr;
   grub_net_network_level_address_t addr;
 
+  name = grub_malloc (grub_strlen (card->name)
+		      + GRUB_NET_MAX_STR_HWADDR_LEN
+		      + sizeof (":link"));
+  if (!name)
+    return NULL;
+
   addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
   addr.ipv6[0] = grub_cpu_to_be64 (0xfe80ULL << 48);
   addr.ipv6[1] = grub_net_ipv6_get_id (hwaddr);
@@ -274,7 +325,7 @@ grub_net_ipv6_get_link_local (struct gru
       ptr += grub_strlen (ptr);
     }
   ptr = grub_stpcpy (ptr, ":link");
-  return grub_net_add_addr (name, card, &addr, hwaddr, 0);
+  return grub_net_add_addr_real (name, card, &addr, hwaddr, 0);
 }
 
 /* FIXME: allow to specify mac address.  */
@@ -882,30 +933,36 @@ grub_net_network_level_interface_registe
 {
   {
     char buf[GRUB_NET_MAX_STR_HWADDR_LEN];
-    char name[grub_strlen (inter->name) + sizeof ("net__mac")];
+    char *name;
     char *ptr;
     grub_net_hwaddr_to_str (&inter->hwaddress, buf);
-    grub_snprintf (name, sizeof (name), "net_%s_mac", inter->name);
+    name = grub_xasprintf ("net_%s_mac", inter->name);
+    if (!name)
+      return;
     for (ptr = name; *ptr; ptr++)
       if (*ptr == ':')
 	*ptr = '_';    
     grub_env_set (name, buf);
     grub_register_variable_hook (name, 0, hwaddr_set_env);
     grub_env_export (name);
+    grub_free (name);
   }
 
   {
     char buf[GRUB_NET_MAX_STR_ADDR_LEN];
-    char name[grub_strlen (inter->name) + sizeof ("net__ip")];
+    char *name;
     char *ptr;
     grub_net_addr_to_str (&inter->address, buf);
-    grub_snprintf (name, sizeof (name), "net_%s_ip", inter->name);
+    name = grub_xasprintf ("net_%s_ip", inter->name);
+    if (!name)
+      return;
     for (ptr = name; *ptr; ptr++)
       if (*ptr == ':')
 	*ptr = '_';    
     grub_env_set (name, buf);
     grub_register_variable_hook (name, 0, addr_set_env);
     grub_env_export (name);
+    grub_free (name);
   }
 
   inter->card->num_ifaces++;
@@ -916,31 +973,6 @@ grub_net_network_level_interface_registe
   grub_net_network_level_interfaces = inter;
 }
 
-struct grub_net_network_level_interface *
-grub_net_add_addr (const char *name, 
-		   struct grub_net_card *card,
-		   const grub_net_network_level_address_t *addr,
-		   const grub_net_link_level_address_t *hwaddress,
-		   grub_net_interface_flags_t flags)
-{
-  struct grub_net_network_level_interface *inter;
-
-  inter = grub_zalloc (sizeof (*inter));
-  if (!inter)
-    return NULL;
-
-  inter->name = grub_strdup (name);
-  grub_memcpy (&(inter->address), addr, sizeof (inter->address));
-  grub_memcpy (&(inter->hwaddress), hwaddress, sizeof (inter->hwaddress));
-  inter->flags = flags;
-  inter->card = card;
-  inter->dhcp_ack = NULL;
-  inter->dhcp_acklen = 0;
-
-  grub_net_network_level_interface_register (inter);
-
-  return inter;
-}
 
 grub_err_t
 grub_net_add_ipv4_local (struct grub_net_network_level_interface *inter,
