From 65cec8deee62996af5d5b05eee248f31d2bd1a4f Mon Sep 17 00:00:00 2001
From: hniksic <devnull@localhost>
Date: Wed, 1 Oct 2003 12:59:48 -0700
Subject: [PATCH] [svn] Fix memory leak in a rare case in url.c. Translate
 error messages from url_parse().

---
 src/ChangeLog |  8 ++++++
 src/url.c     | 73 +++++++++++++++++++++++++++++----------------------
 src/wget.h    |  3 +++
 3 files changed, 53 insertions(+), 31 deletions(-)

diff --git a/src/ChangeLog b/src/ChangeLog
index d11c963f..84aaebdd 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,11 @@
+2003-10-01  Hrvoje Niksic  <hniksic@xemacs.org>
+
+	* url.c (url_parse): Don't leak memory when a reencoded URL turns
+	out to be invalid.
+
+	* url.c (parse_errors): Mark error messages for translation.
+	(url_error): Translate error messages returned to the caller.
+
 2003-10-01  Hrvoje Niksic  <hniksic@xemacs.org>
 
 	* ftp.c (ftp_loop_internal): Initialize TMRATE to NULL to shut up
diff --git a/src/url.c b/src/url.c
index 5468d9c9..cf95c126 100644
--- a/src/url.c
+++ b/src/url.c
@@ -618,28 +618,23 @@ lowercase_str (char *str)
 
 static char *parse_errors[] = {
 #define PE_NO_ERROR			0
-  "No error",
+  N_("No error"),
 #define PE_UNSUPPORTED_SCHEME		1
-  "Unsupported scheme",
+  N_("Unsupported scheme"),
 #define PE_EMPTY_HOST			2
-  "Empty host",
+  N_("Empty host"),
 #define PE_BAD_PORT_NUMBER		3
-  "Bad port number",
+  N_("Bad port number"),
 #define PE_INVALID_USER_NAME		4
-  "Invalid user name",
+  N_("Invalid user name"),
 #define PE_UNTERMINATED_IPV6_ADDRESS	5
-  "Unterminated IPv6 numeric address",
+  N_("Unterminated IPv6 numeric address"),
 #define PE_IPV6_NOT_SUPPORTED		6
-  "IPv6 addresses not supported",
+  N_("IPv6 addresses not supported"),
 #define PE_INVALID_IPV6_ADDRESS		7
-  "Invalid IPv6 numeric address"
+  N_("Invalid IPv6 numeric address")
 };
 
-#define SETERR(p, v) do {			\
-  if (p)					\
-    *(p) = (v);					\
-} while (0)
-
 #ifdef ENABLE_IPV6
 /* The following two functions were adapted from glibc. */
 
@@ -800,13 +795,15 @@ url_parse (const char *url, int *error)
   int port;
   char *user = NULL, *passwd = NULL;
 
-  char *url_encoded;
+  char *url_encoded = NULL;
+
+  int error_code;
 
   scheme = url_scheme (url);
   if (scheme == SCHEME_INVALID)
     {
-      SETERR (error, PE_UNSUPPORTED_SCHEME);
-      return NULL;
+      error_code = PE_UNSUPPORTED_SCHEME;
+      goto error;
     }
 
   url_encoded = reencode_escapes (url);
@@ -843,23 +840,23 @@ url_parse (const char *url, int *error)
 
       if (!host_e)
 	{
-	  SETERR (error, PE_UNTERMINATED_IPV6_ADDRESS);
-	  return NULL;
+	  error_code = PE_UNTERMINATED_IPV6_ADDRESS;
+	  goto error;
 	}
 
 #ifdef ENABLE_IPV6
       /* Check if the IPv6 address is valid. */
       if (!is_valid_ipv6_address(host_b, host_e))
 	{
-	  SETERR (error, PE_INVALID_IPV6_ADDRESS);
-	  return NULL;
+	  error_code = PE_INVALID_IPV6_ADDRESS;
+	  goto error;
 	}
 
       /* Continue parsing after the closing ']'. */
       p = host_e + 1;
 #else
-      SETERR (error, PE_IPV6_NOT_SUPPORTED);
-      return NULL;
+      error_code = PE_IPV6_NOT_SUPPORTED;
+      goto error;
 #endif
     }
   else
@@ -870,8 +867,8 @@ url_parse (const char *url, int *error)
 
   if (host_b == host_e)
     {
-      SETERR (error, PE_EMPTY_HOST);
-      return NULL;
+      error_code = PE_EMPTY_HOST;
+      goto error;
     }
 
   port = scheme_default_port (scheme);
@@ -890,8 +887,8 @@ url_parse (const char *url, int *error)
 	{
 	  /* http://host:/whatever */
 	  /*             ^         */
-	  SETERR (error, PE_BAD_PORT_NUMBER);
-	  return NULL;
+          error_code = PE_BAD_PORT_NUMBER;
+	  goto error;
 	}
 
       for (port = 0, pp = port_b; pp < port_e; pp++)
@@ -900,8 +897,8 @@ url_parse (const char *url, int *error)
 	    {
 	      /* http://host:12randomgarbage/blah */
 	      /*               ^                  */
-	      SETERR (error, PE_BAD_PORT_NUMBER);
-	      return NULL;
+              error_code = PE_BAD_PORT_NUMBER;
+              goto error;
 	    }
 	  
 	  port = 10 * port + (*pp - '0');
@@ -960,8 +957,8 @@ url_parse (const char *url, int *error)
       /*     uname_b   uname_e */
       if (!parse_credentials (uname_b, uname_e - 1, &user, &passwd))
 	{
-	  SETERR (error, PE_INVALID_USER_NAME);
-	  return NULL;
+	  error_code = PE_INVALID_USER_NAME;
+	  goto error;
 	}
     }
 
@@ -1007,13 +1004,27 @@ url_parse (const char *url, int *error)
   url_encoded = NULL;
 
   return u;
+
+ error:
+  /* Cleanup in case of error: */
+  if (url_encoded && url_encoded != url)
+    xfree (url_encoded);
+
+  /* Transmit the error code to the caller, if the caller wants to
+     know.  */
+  if (error)
+    *error = error_code;
+  return NULL;
 }
 
+/* Return the error message string from ERROR_CODE, which should have
+   been retrieved from url_parse.  The error message is translated.  */
+
 const char *
 url_error (int error_code)
 {
   assert (error_code >= 0 && error_code < countof (parse_errors));
-  return parse_errors[error_code];
+  return _(parse_errors[error_code]);
 }
 
 /* Split PATH into DIR and FILE.  PATH comes from the URL and is
diff --git a/src/wget.h b/src/wget.h
index 1c06db05..45e2fd82 100644
--- a/src/wget.h
+++ b/src/wget.h
@@ -62,6 +62,9 @@ so, delete this exception statement from your version.  */
 # define _(string) string
 #endif /* not HAVE_NLS */
 
+/* No-op version of gettext, used for constant strings. */
+#define N_(string) (string)
+
 /* I18N NOTE: You will notice that none of the DEBUG messages are
    marked as translatable.  This is intentional, for a few reasons: