[PATCH] diagnose invalid host and port command line arguments; don't modify ARGV

Jim Meyering jim at meyering.net
Mon Aug 8 10:08:54 UTC 2011


There was inadequate verification of command line HOST:PORT (-d and -m)
and -p PORT arguments and some duplicate code.  The patch below factors
out the duplication and adds checks to catch/diagnose invalid inputs.
Along the way, it also resolves BZ 728623.

>From 9dbd0d54065531654b42224931f4abb2a6685374 Mon Sep 17 00:00:00 2001
From: Jim Meyering <meyering at redhat.com>
Date: Mon, 8 Aug 2011 11:57:38 +0200
Subject: [PATCH] diagnose invalid host and port command line arguments; don't
 modify ARGV

* rest.c (get_port, extract_host_port): New functions.
(main): Use them to parse arguments to the -d, -m and -p options.
Before, a missing host name part and/or an invalid port number
would not have been diagnosed.
By no longer modifying "optarg", this address
http://bugzilla.redhat.com/728623
---
 rest.c |   52 +++++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 39 insertions(+), 13 deletions(-)

diff --git a/rest.c b/rest.c
index a54fabd..6125275 100644
--- a/rest.c
+++ b/rest.c
@@ -51,6 +51,8 @@
 #include "mpipe.h"
 #include "state_defs.h"
 #include "version-etc.h"
+#include "xstrndup.h"
+#include "xstrtol.h"

 const char version_etc_copyright[] =
   /* Do *not* mark this string for translation.  %s is a copyright
@@ -2373,13 +2375,42 @@ Report %s bugs to %s.\n\
   exit (status);
 }

+/* Return the integer representation of PORT_STR.  Exit nonzero if
+   PORT_STR is not a valid valid unsigned integer <= SHRT_MAX  */
+static unsigned short
+get_port (char const *port_str)
+{
+	unsigned long port_tmp;
+	if (xstrtoul (port_str, NULL, 10, &port_tmp, NULL) != LONGINT_OK
+	    || USHRT_MAX < port_tmp)
+		error (EXIT_FAILURE, 0, _("invalid port number: %s"), port_str);
+	return port_tmp;
+}
+
+/* Given a string S of the form "HOST:PORT_STR" or "HOST", set *HOSTNAME to a
+   malloc'd string containing HOST, and if there's a colon, set *PORT to the
+   port number.  Diagnose and exit nonzero if the hostname part is empty
+   or if the port string is not a valid unsigned integer <= SHRT_MAX.  */
+static void
+extract_host_port (char const *s, const char **hostname, unsigned short *port)
+{
+	assert (s);
+	size_t s_len = strlen (s);
+	char const *colon = memchr (s, ':', s_len);
+	size_t hostname_len = colon ? colon - s : s_len;
+	if (hostname_len == 0)
+		error (EXIT_FAILURE, 0, _("invalid host name"));
+	*hostname = xstrndup (s, hostname_len);
+
+	if (colon)
+		*port = get_port (colon + 1);
+}
+
 int
 main (int argc, char **argv)
 {
 	struct MHD_Daemon	*the_daemon;
 	sem_t			 the_sem;
-	char			*stctx = NULL;
-	char			*port_tmp;
 	bool			 autostart = false;
 	char *cfg_file = NULL;

@@ -2402,11 +2433,8 @@ main (int argc, char **argv)
 		break;
 	case 'd':
 		assert (optarg);
-		db_host = strtok_r(optarg,":",&stctx);
-		port_tmp = strtok_r(NULL,":",&stctx);
-		if (port_tmp) {
-			db_port = (unsigned short)strtoul(port_tmp,NULL,10);
-		}
+		free (db_host); db_host = NULL;
+		extract_host_port (optarg, &db_host, &db_port);
 		break;
 	case 'l':
 		assert (optarg);
@@ -2414,14 +2442,12 @@ main (int argc, char **argv)
 		break;
 	case 'm':
 		assert (optarg);
-		master_host = strtok_r(optarg,":",&stctx);
-		port_tmp = strtok_r(NULL,":",&stctx);
-		if (port_tmp) {
-			master_port = (unsigned short)strtoul(port_tmp,NULL,10);
-		}
+		free (master_host); master_host = NULL;
+		extract_host_port (optarg, &master_host, &master_port);
 		break;
 	case 'p':
-		my_port = (unsigned short)strtoul(optarg,NULL,10);
+		assert (optarg);
+		my_port = get_port (optarg);
 		break;
 	case 'v':
 		++verbose;
--
1.7.6.351.gb35ac


More information about the iwhd-devel mailing list