VPP-635: CLI Memory leak with invalid parameter

In the CLI parsing, below is a common pattern:
  /* Get a line of input. */
  if (!unformat_user (input, unformat_line_input, line_input))
    return 0;

  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (line_input, "x"))
	x = 1;
      :
      else
	return clib_error_return (0, "unknown input `%U'",
				  format_unformat_error, line_input);
    }
  unformat_free (line_input);

The 'else' returns if an unknown string is encountered. There a memory
leak because the 'unformat_free(line_input)' is not called. There is a
large number of instances of this pattern.

Replaced the previous pattern with:
  /* Get a line of input. */
  if (!unformat_user (input, unformat_line_input, line_input))
    return 0;

  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (line_input, "x"))
	x = 1;
      :
      else
        {
	  error = clib_error_return (0, "unknown input `%U'",
				     format_unformat_error, line_input);
	  goto done:
        }
    }

  /* ...Remaining code... */

done:
  unformat_free (line_input);
  return error;
}

In multiple files, 'unformat_free (line_input);' was never called, so
there was a memory leak whether an invalid string was entered or not.

Also, there were multiple instance where:
	  error = clib_error_return (0, "unknown input `%U'",
				     format_unformat_error, line_input);
used 'input' as the last parameter instead of 'line_input'. The result
is that output did not contain the substring in error, instead just an
empty string. Fixed all of those as well.

There are a lot of file, and very mind numbing work, so tried to keep
it to a pattern to avoid mistakes.

Change-Id: I8902f0c32a47dd7fb3bb3471a89818571702f1d2
Signed-off-by: Billy McFall <bmcfall@redhat.com>
Signed-off-by: Dave Barach <dave@barachs.net>
diff --git a/src/vnet/devices/af_packet/cli.c b/src/vnet/devices/af_packet/cli.c
index 6baa26e..d4aa701 100644
--- a/src/vnet/devices/af_packet/cli.c
+++ b/src/vnet/devices/af_packet/cli.c
@@ -49,6 +49,7 @@
   u8 *hw_addr_ptr = 0;
   u32 sw_if_index;
   int r;
+  clib_error_t *error = NULL;
 
   /* Get a line of input. */
   if (!unformat_user (input, unformat_line_input, line_input))
@@ -63,29 +64,47 @@
 	    (line_input, "hw-addr %U", unformat_ethernet_address, hwaddr))
 	hw_addr_ptr = hwaddr;
       else
-	return clib_error_return (0, "unknown input `%U'",
-				  format_unformat_error, input);
+	{
+	  error = clib_error_return (0, "unknown input `%U'",
+				     format_unformat_error, line_input);
+	  goto done;
+	}
     }
-  unformat_free (line_input);
 
   if (host_if_name == NULL)
-    return clib_error_return (0, "missing host interface name");
+    {
+      error = clib_error_return (0, "missing host interface name");
+      goto done;
+    }
 
   r = af_packet_create_if (vm, host_if_name, hw_addr_ptr, &sw_if_index);
-  vec_free (host_if_name);
 
   if (r == VNET_API_ERROR_SYSCALL_ERROR_1)
-    return clib_error_return (0, "%s (errno %d)", strerror (errno), errno);
+    {
+      error = clib_error_return (0, "%s (errno %d)", strerror (errno), errno);
+      goto done;
+    }
 
   if (r == VNET_API_ERROR_INVALID_INTERFACE)
-    return clib_error_return (0, "Invalid interface name");
+    {
+      error = clib_error_return (0, "Invalid interface name");
+      goto done;
+    }
 
   if (r == VNET_API_ERROR_SUBIF_ALREADY_EXISTS)
-    return clib_error_return (0, "Interface elready exists");
+    {
+      error = clib_error_return (0, "Interface elready exists");
+      goto done;
+    }
 
   vlib_cli_output (vm, "%U\n", format_vnet_sw_if_index_name, vnet_get_main (),
 		   sw_if_index);
-  return 0;
+
+done:
+  vec_free (host_if_name);
+  unformat_free (line_input);
+
+  return error;
 }
 
 /*?
@@ -124,6 +143,7 @@
 {
   unformat_input_t _line_input, *line_input = &_line_input;
   u8 *host_if_name = NULL;
+  clib_error_t *error = NULL;
 
   /* Get a line of input. */
   if (!unformat_user (input, unformat_line_input, line_input))
@@ -134,18 +154,26 @@
       if (unformat (line_input, "name %s", &host_if_name))
 	;
       else
-	return clib_error_return (0, "unknown input `%U'",
-				  format_unformat_error, input);
+	{
+	  error = clib_error_return (0, "unknown input `%U'",
+				     format_unformat_error, line_input);
+	  goto done;
+	}
     }
-  unformat_free (line_input);
 
   if (host_if_name == NULL)
-    return clib_error_return (0, "missing host interface name");
+    {
+      error = clib_error_return (0, "missing host interface name");
+      goto done;
+    }
 
   af_packet_delete_if (vm, host_if_name);
-  vec_free (host_if_name);
 
-  return 0;
+done:
+  vec_free (host_if_name);
+  unformat_free (line_input);
+
+  return error;
 }
 
 /*?
diff --git a/src/vnet/devices/dpdk/cli.c b/src/vnet/devices/dpdk/cli.c
index d133cfd..1fc665a 100644
--- a/src/vnet/devices/dpdk/cli.c
+++ b/src/vnet/devices/dpdk/cli.c
@@ -398,7 +398,7 @@
   u32 hw_if_index = (u32) ~ 0;
   u32 nb_rx_desc = (u32) ~ 0;
   u32 nb_tx_desc = (u32) ~ 0;
-  clib_error_t *rv;
+  clib_error_t *error = NULL;
 
   if (!unformat_user (input, unformat_line_input, line_input))
     return 0;
@@ -414,25 +414,37 @@
       else if (unformat (line_input, "rx %d", &nb_rx_desc))
 	;
       else
-	return clib_error_return (0, "parse error: '%U'",
-				  format_unformat_error, line_input);
+	{
+	  error = clib_error_return (0, "parse error: '%U'",
+				     format_unformat_error, line_input);
+	  goto done;
+	}
     }
 
-  unformat_free (line_input);
-
   if (hw_if_index == (u32) ~ 0)
-    return clib_error_return (0, "please specify valid interface name");
+    {
+      error = clib_error_return (0, "please specify valid interface name");
+      goto done;
+    }
 
   hw = vnet_get_hw_interface (dm->vnet_main, hw_if_index);
   xd = vec_elt_at_index (dm->devices, hw->dev_instance);
 
   if ((xd->flags & DPDK_DEVICE_FLAG_PMD) == 0)
-    return clib_error_return (0, "number of descriptors can be set only for "
-			      "physical devices");
+    {
+      error =
+	clib_error_return (0,
+			   "number of descriptors can be set only for "
+			   "physical devices");
+      goto done;
+    }
 
   if ((nb_rx_desc == (u32) ~ 0 || nb_rx_desc == xd->nb_rx_desc) &&
       (nb_tx_desc == (u32) ~ 0 || nb_tx_desc == xd->nb_tx_desc))
-    return clib_error_return (0, "nothing changed");
+    {
+      error = clib_error_return (0, "nothing changed");
+      goto done;
+    }
 
   if (nb_rx_desc != (u32) ~ 0)
     xd->nb_rx_desc = nb_rx_desc;
@@ -440,9 +452,12 @@
   if (nb_tx_desc != (u32) ~ 0)
     xd->nb_tx_desc = nb_tx_desc;
 
-  rv = dpdk_port_setup (dm, xd);
+  error = dpdk_port_setup (dm, xd);
 
-  return rv;
+done:
+  unformat_free (line_input);
+
+  return error;
 }
 
 /* *INDENT-OFF* */
@@ -523,6 +538,7 @@
   u32 queue = (u32) 0;
   u32 cpu = (u32) ~ 0;
   int i;
+  clib_error_t *error = NULL;
 
   if (!unformat_user (input, unformat_line_input, line_input))
     return 0;
@@ -538,18 +554,25 @@
       else if (unformat (line_input, "thread %d", &cpu))
 	;
       else
-	return clib_error_return (0, "parse error: '%U'",
-				  format_unformat_error, line_input);
+	{
+	  error = clib_error_return (0, "parse error: '%U'",
+				     format_unformat_error, line_input);
+	  goto done;
+	}
     }
 
-  unformat_free (line_input);
-
   if (hw_if_index == (u32) ~ 0)
-    return clib_error_return (0, "please specify valid interface name");
+    {
+      error = clib_error_return (0, "please specify valid interface name");
+      goto done;
+    }
 
   if (cpu < dm->input_cpu_first_index ||
       cpu >= (dm->input_cpu_first_index + dm->input_cpu_count))
-    return clib_error_return (0, "please specify valid thread id");
+    {
+      error = clib_error_return (0, "please specify valid thread id");
+      goto done;
+    }
 
   hw = vnet_get_hw_interface (dm->vnet_main, hw_if_index);
   xd = vec_elt_at_index (dm->devices, hw->dev_instance);
@@ -563,7 +586,7 @@
               queue == dq->queue_id)
             {
               if (cpu == i) /* nothing to do */
-                return 0;
+                goto done;
 
               vec_del1(dm->devices_by_cpu[i], dq - dm->devices_by_cpu[i]);
               vec_add2(dm->devices_by_cpu[cpu], dq, 1);
@@ -586,13 +609,18 @@
                 vlib_node_set_state (vlib_mains[cpu], dpdk_input_node.index,
                                      VLIB_NODE_STATE_POLLING);
 
-              return 0;
+              goto done;
             }
         }
       /* *INDENT-ON* */
     }
 
-  return clib_error_return (0, "not found");
+  error = clib_error_return (0, "not found");
+
+done:
+  unformat_free (line_input);
+
+  return error;
 }
 
 /* *INDENT-OFF* */
@@ -653,6 +681,7 @@
   u32 hw_if_index = (u32) ~ 0;
   u32 cpu = (u32) ~ 0;
   int i;
+  clib_error_t *error = NULL;
 
   if (!unformat_user (input, unformat_line_input, line_input))
     return 0;
@@ -666,18 +695,22 @@
       else if (unformat (line_input, "thread %d", &cpu))
 	;
       else
-	return clib_error_return (0, "parse error: '%U'",
-				  format_unformat_error, line_input);
+	{
+	  error = clib_error_return (0, "parse error: '%U'",
+				     format_unformat_error, line_input);
+	  goto done;
+	}
     }
 
-  unformat_free (line_input);
-
   if (hw_if_index == (u32) ~ 0)
     return clib_error_return (0, "please specify valid interface name");
 
   if (cpu < dm->hqos_cpu_first_index ||
       cpu >= (dm->hqos_cpu_first_index + dm->hqos_cpu_count))
-    return clib_error_return (0, "please specify valid thread id");
+    {
+      error = clib_error_return (0, "please specify valid thread id");
+      goto done;
+    }
 
   hw = vnet_get_hw_interface (dm->vnet_main, hw_if_index);
   xd = vec_elt_at_index (dm->devices, hw->dev_instance);
@@ -689,7 +722,7 @@
 	if (hw_if_index == dm->devices[dq->device].vlib_hw_if_index)
 	  {
 	    if (cpu == i)	/* nothing to do */
-	      return 0;
+	      goto done;
 
 	    vec_del1 (dm->devices_by_hqos_cpu[i],
 		      dq - dm->devices_by_hqos_cpu[i]);
@@ -703,12 +736,17 @@
 	    vec_sort_with_function (dm->devices_by_hqos_cpu[cpu],
 				    dpdk_device_queue_sort);
 
-	    return 0;
+	    goto done;
 	  }
       }
     }
 
-  return clib_error_return (0, "not found");
+  error = clib_error_return (0, "not found");
+
+done:
+  unformat_free (line_input);
+
+  return error;
 }
 
 /* *INDENT-OFF* */
@@ -732,6 +770,7 @@
   u32 pipe_id = (u32) ~ 0;
   u32 profile_id = (u32) ~ 0;
   int rv;
+  clib_error_t *error = NULL;
 
   if (!unformat_user (input, unformat_line_input, line_input))
     return 0;
@@ -749,14 +788,18 @@
       else if (unformat (line_input, "profile %d", &profile_id))
 	;
       else
-	return clib_error_return (0, "parse error: '%U'",
-				  format_unformat_error, line_input);
+	{
+	  error = clib_error_return (0, "parse error: '%U'",
+				     format_unformat_error, line_input);
+	  goto done;
+	}
     }
 
-  unformat_free (line_input);
-
   if (hw_if_index == (u32) ~ 0)
-    return clib_error_return (0, "please specify valid interface name");
+    {
+      error = clib_error_return (0, "please specify valid interface name");
+      goto done;
+    }
 
   hw = vnet_get_hw_interface (dm->vnet_main, hw_if_index);
   xd = vec_elt_at_index (dm->devices, hw->dev_instance);
@@ -765,9 +808,15 @@
     rte_sched_pipe_config (xd->hqos_ht->hqos, subport_id, pipe_id,
 			   profile_id);
   if (rv)
-    return clib_error_return (0, "pipe configuration failed");
+    {
+      error = clib_error_return (0, "pipe configuration failed");
+      goto done;
+    }
 
-  return 0;
+done:
+  unformat_free (line_input);
+
+  return error;
 }
 
 /* *INDENT-OFF* */
@@ -797,6 +846,7 @@
     .tc_period = 10,
   };
   int rv;
+  clib_error_t *error = NULL;
 
   if (!unformat_user (input, unformat_line_input, line_input))
     return 0;
@@ -829,23 +879,33 @@
       else if (unformat (line_input, "period %d", &p.tc_period))
 	;
       else
-	return clib_error_return (0, "parse error: '%U'",
-				  format_unformat_error, line_input);
+	{
+	  error = clib_error_return (0, "parse error: '%U'",
+				     format_unformat_error, line_input);
+	  goto done;
+	}
     }
 
-  unformat_free (line_input);
-
   if (hw_if_index == (u32) ~ 0)
-    return clib_error_return (0, "please specify valid interface name");
+    {
+      error = clib_error_return (0, "please specify valid interface name");
+      goto done;
+    }
 
   hw = vnet_get_hw_interface (dm->vnet_main, hw_if_index);
   xd = vec_elt_at_index (dm->devices, hw->dev_instance);
 
   rv = rte_sched_subport_config (xd->hqos_ht->hqos, subport_id, &p);
   if (rv)
-    return clib_error_return (0, "subport configuration failed");
+    {
+      error = clib_error_return (0, "subport configuration failed");
+      goto done;
+    }
 
-  return 0;
+done:
+  unformat_free (line_input);
+
+  return error;
 }
 
 /* *INDENT-OFF* */
@@ -872,6 +932,7 @@
   u32 queue = (u32) ~ 0;
   u32 entry = (u32) ~ 0;
   u32 val, i;
+  clib_error_t *error = NULL;
 
   if (!unformat_user (input, unformat_line_input, line_input))
     return 0;
@@ -889,20 +950,33 @@
       else if (unformat (line_input, "queue %d", &queue))
 	;
       else
-	return clib_error_return (0, "parse error: '%U'",
-				  format_unformat_error, line_input);
+	{
+	  error = clib_error_return (0, "parse error: '%U'",
+				     format_unformat_error, line_input);
+	  goto done;
+	}
     }
 
-  unformat_free (line_input);
-
   if (hw_if_index == (u32) ~ 0)
-    return clib_error_return (0, "please specify valid interface name");
+    {
+      error = clib_error_return (0, "please specify valid interface name");
+      goto done;
+    }
   if (entry >= 64)
-    return clib_error_return (0, "invalid entry");
+    {
+      error = clib_error_return (0, "invalid entry");
+      goto done;
+    }
   if (tc >= RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE)
-    return clib_error_return (0, "invalid traffic class");
+    {
+      error = clib_error_return (0, "invalid traffic class");
+      goto done;
+    }
   if (queue >= RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS)
-    return clib_error_return (0, "invalid traffic class");
+    {
+      error = clib_error_return (0, "invalid traffic class");
+      goto done;
+    }
 
   hw = vnet_get_hw_interface (dm->vnet_main, hw_if_index);
   xd = vec_elt_at_index (dm->devices, hw->dev_instance);
@@ -911,7 +985,10 @@
   uword *p = hash_get_mem (tm->thread_registrations_by_name, "workers");
   /* Should never happen, shut up Coverity warning */
   if (p == 0)
-    return clib_error_return (0, "no worker registrations?");
+    {
+      error = clib_error_return (0, "no worker registrations?");
+      goto done;
+    }
 
   vlib_thread_registration_t *tr = (vlib_thread_registration_t *) p[0];
   int worker_thread_first = tr->first_index;
@@ -921,7 +998,10 @@
   for (i = 0; i < worker_thread_count; i++)
     xd->hqos_wt[worker_thread_first + i].hqos_tc_table[entry] = val;
 
-  return 0;
+done:
+  unformat_free (line_input);
+
+  return error;
 }
 
 /* *INDENT-OFF* */
@@ -939,6 +1019,7 @@
   unformat_input_t _line_input, *line_input = &_line_input;
   vlib_thread_main_t *tm = vlib_get_thread_main ();
   dpdk_main_t *dm = &dpdk_main;
+  clib_error_t *error = NULL;
 
   /* Device specific data */
   struct rte_eth_dev_info dev_info;
@@ -984,15 +1065,19 @@
       else if (unformat (line_input, "mask %llx", &mask))
 	;
       else
-	return clib_error_return (0, "parse error: '%U'",
-				  format_unformat_error, line_input);
+	{
+	  error = clib_error_return (0, "parse error: '%U'",
+				     format_unformat_error, line_input);
+	  goto done;
+	}
     }
 
-  unformat_free (line_input);
-
   /* Get interface */
   if (hw_if_index == (u32) ~ 0)
-    return clib_error_return (0, "please specify valid interface name");
+    {
+      error = clib_error_return (0, "please specify valid interface name");
+      goto done;
+    }
 
   hw = vnet_get_hw_interface (dm->vnet_main, hw_if_index);
   xd = vec_elt_at_index (dm->devices, hw->dev_instance);
@@ -1019,7 +1104,7 @@
   if (devconf->hqos_enabled == 0)
     {
       vlib_cli_output (vm, "HQoS disabled for this interface");
-      return 0;
+      goto done;
     }
 
   n_subports_per_port = devconf->hqos.port.n_subports_per_port;
@@ -1028,27 +1113,39 @@
 
   /* Validate packet field configuration: id, offset and mask */
   if (id >= 3)
-    return clib_error_return (0, "invalid packet field id");
+    {
+      error = clib_error_return (0, "invalid packet field id");
+      goto done;
+    }
 
   switch (id)
     {
     case 0:
       if (dpdk_hqos_validate_mask (mask, n_subports_per_port) != 0)
-	return clib_error_return (0, "invalid subport ID mask "
-				  "(n_subports_per_port = %u)",
-				  n_subports_per_port);
+	{
+	  error = clib_error_return (0, "invalid subport ID mask "
+				     "(n_subports_per_port = %u)",
+				     n_subports_per_port);
+	  goto done;
+	}
       break;
     case 1:
       if (dpdk_hqos_validate_mask (mask, n_pipes_per_subport) != 0)
-	return clib_error_return (0, "invalid pipe ID mask "
-				  "(n_pipes_per_subport = %u)",
-				  n_pipes_per_subport);
+	{
+	  error = clib_error_return (0, "invalid pipe ID mask "
+				     "(n_pipes_per_subport = %u)",
+				     n_pipes_per_subport);
+	  goto done;
+	}
       break;
     case 2:
     default:
       if (dpdk_hqos_validate_mask (mask, tctbl_size) != 0)
-	return clib_error_return (0, "invalid TC table index mask "
-				  "(TC table size = %u)", tctbl_size);
+	{
+	  error = clib_error_return (0, "invalid TC table index mask "
+				     "(TC table size = %u)", tctbl_size);
+	  goto done;
+	}
     }
 
   /* Propagate packet field configuration to all workers */
@@ -1075,7 +1172,10 @@
 	  __builtin_ctzll (mask);
       }
 
-  return 0;
+done:
+  unformat_free (line_input);
+
+  return error;
 }
 
 /* *INDENT-OFF* */
@@ -1106,6 +1206,7 @@
   dpdk_device_config_t *devconf = 0;
   vlib_thread_registration_t *tr;
   uword *p = 0;
+  clib_error_t *error = NULL;
 
   if (!unformat_user (input, unformat_line_input, line_input))
     return 0;
@@ -1117,14 +1218,18 @@
 	   &hw_if_index))
 	;
       else
-	return clib_error_return (0, "parse error: '%U'",
-				  format_unformat_error, line_input);
+	{
+	  error = clib_error_return (0, "parse error: '%U'",
+				     format_unformat_error, line_input);
+	  goto done;
+	}
     }
 
-  unformat_free (line_input);
-
   if (hw_if_index == (u32) ~ 0)
-    return clib_error_return (0, "please specify interface name!!");
+    {
+      error = clib_error_return (0, "please specify interface name!!");
+      goto done;
+    }
 
   hw = vnet_get_hw_interface (dm->vnet_main, hw_if_index);
   xd = vec_elt_at_index (dm->devices, hw->dev_instance);
@@ -1151,7 +1256,7 @@
   if (devconf->hqos_enabled == 0)
     {
       vlib_cli_output (vm, "HQoS disabled for this interface");
-      return 0;
+      goto done;
     }
 
   /* Detect the set of worker threads */
@@ -1159,7 +1264,10 @@
 
   /* Should never happen, shut up Coverity warning */
   if (p == 0)
-    return clib_error_return (0, "no worker registrations?");
+    {
+      error = clib_error_return (0, "no worker registrations?");
+      goto done;
+    }
 
   tr = (vlib_thread_registration_t *) p[0];
 
@@ -1284,7 +1392,10 @@
     }
 #endif
 
-  return 0;
+done:
+  unformat_free (line_input);
+
+  return error;
 }
 
 /* *INDENT-OFF* */
@@ -1315,6 +1426,7 @@
   u32 qindex;
   struct rte_sched_queue_stats stats;
   u16 qlen;
+  clib_error_t *error = NULL;
 
   if (!unformat_user (input, unformat_line_input, line_input))
     return 0;
@@ -1339,14 +1451,18 @@
 	;
 
       else
-	return clib_error_return (0, "parse error: '%U'",
-				  format_unformat_error, line_input);
+	{
+	  error = clib_error_return (0, "parse error: '%U'",
+				     format_unformat_error, line_input);
+	  goto done;
+	}
     }
 
-  unformat_free (line_input);
-
   if (hw_if_index == (u32) ~ 0)
-    return clib_error_return (0, "please specify interface name!!");
+    {
+      error = clib_error_return (0, "please specify interface name!!");
+      goto done;
+    }
 
   hw = vnet_get_hw_interface (dm->vnet_main, hw_if_index);
   xd = vec_elt_at_index (dm->devices, hw->dev_instance);
@@ -1373,7 +1489,7 @@
   if (devconf->hqos_enabled == 0)
     {
       vlib_cli_output (vm, "HQoS disabled for this interface");
-      return 0;
+      goto done;
     }
 
   /*
@@ -1386,7 +1502,10 @@
 
   if (rte_sched_queue_read_stats (xd->hqos_ht->hqos, qindex, &stats, &qlen) !=
       0)
-    return clib_error_return (0, "failed to read stats");
+    {
+      error = clib_error_return (0, "failed to read stats");
+      goto done;
+    }
 
   vlib_cli_output (vm, "%=24s%=16s", "Stats Parameter", "Value");
   vlib_cli_output (vm, "%=24s%=16d", "Packets", stats.n_pkts);
@@ -1399,7 +1518,10 @@
   vlib_cli_output (vm, "%=24s%=16d", "Bytes dropped", stats.n_bytes_dropped);
 
 
-  return 0;
+done:
+  unformat_free (line_input);
+
+  return error;
 }
 
 /* *INDENT-OFF* */
diff --git a/src/vnet/devices/dpdk/ipsec/cli.c b/src/vnet/devices/dpdk/ipsec/cli.c
index 93df4a6..f9d3a5d 100644
--- a/src/vnet/devices/dpdk/ipsec/cli.c
+++ b/src/vnet/devices/dpdk/ipsec/cli.c
@@ -111,6 +111,7 @@
 {
   unformat_input_t _line_input, *line_input = &_line_input;
   u16 detail = 0;
+  clib_error_t *error = NULL;
 
   if (!unformat_user (input, unformat_line_input, line_input))
     return 0;
@@ -120,15 +121,19 @@
       if (unformat (line_input, "verbose"))
 	detail = 1;
       else
-	return clib_error_return (0, "parse error: '%U'",
-				  format_unformat_error, line_input);
+	{
+	  error = clib_error_return (0, "parse error: '%U'",
+				     format_unformat_error, line_input);
+	  goto done;
+	}
     }
 
-  unformat_free (line_input);
-
   dpdk_ipsec_show_mapping (vm, detail);
 
-  return 0;
+done:
+  unformat_free (line_input);
+
+  return error;
 }
 
 /* *INDENT-OFF* */
diff --git a/src/vnet/devices/netmap/cli.c b/src/vnet/devices/netmap/cli.c
index 6157f27..7136329 100644
--- a/src/vnet/devices/netmap/cli.c
+++ b/src/vnet/devices/netmap/cli.c
@@ -37,6 +37,7 @@
   u8 is_pipe = 0;
   u8 is_master = 0;
   u32 sw_if_index = ~0;
+  clib_error_t *error = NULL;
 
   /* Get a line of input. */
   if (!unformat_user (input, unformat_line_input, line_input))
@@ -57,30 +58,48 @@
       else if (unformat (line_input, "slave"))
 	is_master = 0;
       else
-	return clib_error_return (0, "unknown input `%U'",
-				  format_unformat_error, input);
+	{
+	  error = clib_error_return (0, "unknown input `%U'",
+				     format_unformat_error, line_input);
+	  goto done;
+	}
     }
-  unformat_free (line_input);
 
   if (host_if_name == NULL)
-    return clib_error_return (0, "missing host interface name");
+    {
+      error = clib_error_return (0, "missing host interface name");
+      goto done;
+    }
 
   r =
     netmap_create_if (vm, host_if_name, hw_addr_ptr, is_pipe, is_master,
 		      &sw_if_index);
 
   if (r == VNET_API_ERROR_SYSCALL_ERROR_1)
-    return clib_error_return (0, "%s (errno %d)", strerror (errno), errno);
+    {
+      error = clib_error_return (0, "%s (errno %d)", strerror (errno), errno);
+      goto done;
+    }
 
   if (r == VNET_API_ERROR_INVALID_INTERFACE)
-    return clib_error_return (0, "Invalid interface name");
+    {
+      error = clib_error_return (0, "Invalid interface name");
+      goto done;
+    }
 
   if (r == VNET_API_ERROR_SUBIF_ALREADY_EXISTS)
-    return clib_error_return (0, "Interface already exists");
+    {
+      error = clib_error_return (0, "Interface already exists");
+      goto done;
+    }
 
   vlib_cli_output (vm, "%U\n", format_vnet_sw_if_index_name, vnet_get_main (),
 		   sw_if_index);
-  return 0;
+
+done:
+  unformat_free (line_input);
+
+  return error;
 }
 
 /*?
@@ -144,6 +163,7 @@
 {
   unformat_input_t _line_input, *line_input = &_line_input;
   u8 *host_if_name = NULL;
+  clib_error_t *error = NULL;
 
   /* Get a line of input. */
   if (!unformat_user (input, unformat_line_input, line_input))
@@ -154,17 +174,25 @@
       if (unformat (line_input, "name %s", &host_if_name))
 	;
       else
-	return clib_error_return (0, "unknown input `%U'",
-				  format_unformat_error, input);
+	{
+	  error = clib_error_return (0, "unknown input `%U'",
+				     format_unformat_error, line_input);
+	  goto done;
+	}
     }
-  unformat_free (line_input);
 
   if (host_if_name == NULL)
-    return clib_error_return (0, "missing host interface name");
+    {
+      error = clib_error_return (0, "missing host interface name");
+      goto done;
+    }
 
   netmap_delete_if (vm, host_if_name);
 
-  return 0;
+done:
+  unformat_free (line_input);
+
+  return error;
 }
 
 /*?
diff --git a/src/vnet/devices/virtio/vhost-user.c b/src/vnet/devices/virtio/vhost-user.c
index 315daa7..c43f6e6 100644
--- a/src/vnet/devices/virtio/vhost-user.c
+++ b/src/vnet/devices/virtio/vhost-user.c
@@ -2682,6 +2682,7 @@
   u32 custom_dev_instance = ~0;
   u8 hwaddr[6];
   u8 *hw = NULL;
+  clib_error_t *error = NULL;
 
   /* Get a line of input. */
   if (!unformat_user (input, unformat_line_input, line_input))
@@ -2704,10 +2705,12 @@
 	  renumber = 1;
 	}
       else
-	return clib_error_return (0, "unknown input `%U'",
-				  format_unformat_error, input);
+	{
+	  error = clib_error_return (0, "unknown input `%U'",
+				     format_unformat_error, line_input);
+	  goto done;
+	}
     }
-  unformat_free (line_input);
 
   vnet_main_t *vnm = vnet_get_main ();
 
@@ -2716,14 +2719,18 @@
 				  is_server, &sw_if_index, feature_mask,
 				  renumber, custom_dev_instance, hw)))
     {
-      vec_free (sock_filename);
-      return clib_error_return (0, "vhost_user_create_if returned %d", rv);
+      error = clib_error_return (0, "vhost_user_create_if returned %d", rv);
+      goto done;
     }
 
-  vec_free (sock_filename);
   vlib_cli_output (vm, "%U\n", format_vnet_sw_if_index_name, vnet_get_main (),
 		   sw_if_index);
-  return 0;
+
+done:
+  vec_free (sock_filename);
+  unformat_free (line_input);
+
+  return error;
 }
 
 clib_error_t *
@@ -2734,6 +2741,7 @@
   unformat_input_t _line_input, *line_input = &_line_input;
   u32 sw_if_index = ~0;
   vnet_main_t *vnm = vnet_get_main ();
+  clib_error_t *error = NULL;
 
   /* Get a line of input. */
   if (!unformat_user (input, unformat_line_input, line_input))
@@ -2751,15 +2759,25 @@
 	    vnet_get_sup_hw_interface (vnm, sw_if_index);
 	  if (hwif == NULL ||
 	      vhost_user_dev_class.index != hwif->dev_class_index)
-	    return clib_error_return (0, "Not a vhost interface");
+	    {
+	      error = clib_error_return (0, "Not a vhost interface");
+	      goto done;
+	    }
 	}
       else
-	return clib_error_return (0, "unknown input `%U'",
-				  format_unformat_error, input);
+	{
+	  error = clib_error_return (0, "unknown input `%U'",
+				     format_unformat_error, line_input);
+	  goto done;
+	}
     }
-  unformat_free (line_input);
+
   vhost_user_delete_if (vnm, vm, sw_if_index);
-  return 0;
+
+done:
+  unformat_free (line_input);
+
+  return error;
 }
 
 int
@@ -3286,6 +3304,7 @@
   u32 sw_if_index;
   u8 del = 0;
   int rv;
+  clib_error_t *error = NULL;
 
   /* Get a line of input. */
   if (!unformat_user (input, unformat_line_input, line_input))
@@ -3295,9 +3314,9 @@
       (line_input, "%U %d", unformat_vnet_sw_interface, vnet_get_main (),
        &sw_if_index, &worker_thread_index))
     {
-      unformat_free (line_input);
-      return clib_error_return (0, "unknown input `%U'",
-				format_unformat_error, input);
+      error = clib_error_return (0, "unknown input `%U'",
+				 format_unformat_error, line_input);
+      goto done;
     }
 
   if (unformat (line_input, "del"))
@@ -3305,9 +3324,16 @@
 
   if ((rv =
        vhost_user_thread_placement (sw_if_index, worker_thread_index, del)))
-    return clib_error_return (0, "vhost_user_thread_placement returned %d",
-			      rv);
-  return 0;
+    {
+      error = clib_error_return (0, "vhost_user_thread_placement returned %d",
+				 rv);
+      goto done;
+    }
+
+done:
+  unformat_free (line_input);
+
+  return error;
 }