Fixed a memleak found by Zhenbo Xu, reportted on 11.04.2012 to bug-wget.

2012-04-12  Tim Ruehsen  <tim.rueh...@gmx.de>

        * rewrote home_dir() to fix memleak, removed need for freeing home

=== modified file 'src/init.c'
--- src/init.c	2012-03-08 09:00:51 +0000
+++ src/init.c	2012-04-12 11:17:21 +0000
@@ -389,63 +389,62 @@
   opt.warc_keep_log = true;
 }
 
+#if defined(WINDOWS) || defined(MSDOS)
+# define ISSEP(c) ((c) == '/' || (c) == '\\')
+#else
+# define ISSEP(c) ((c) == '/')
+#endif
+
 /* Return the user's home directory (strdup-ed), or NULL if none is
    found.  */
-char *
+const char *
 home_dir (void)
 {
-  static char *buf = NULL;
-  static char *home, *ret;
+  static char *home;
+
+  if (!home)
+    home = getenv ("HOME");
 
   if (!home)
     {
-      home = getenv ("HOME");
-      if (!home)
-        {
 #if defined(MSDOS)
-          int len;
-
-          /* Under MSDOS, if $HOME isn't defined, use the directory where
-             `wget.exe' resides.  */
-          const char *_w32_get_argv0 (void); /* in libwatt.a/pcconfig.c */
-          char *p;
-
-          buff = _w32_get_argv0 ();
-
-          p = strrchr (buf, '/');            /* djgpp */
-          if (!p)
-            p = strrchr (buf, '\\');          /* others */
-          assert (p);
-
-          len = p - buff + 1;
-          buff = malloc (len + 1);
-          if (buff == NULL)
-            return NULL;
-
-          strncpy (buff, _w32_get_argv0 (), len);
-          buff[len] = '\0';
-
-          home = buf;
+    /* Under MSDOS, if $HOME isn't defined, use the directory where
+      `wget.exe' resides.  */
+    const char *_w32_get_argv0 (void); /* in libwatt.a/pcconfig.c */
+    char *p, *path;
+    int len;
+
+    path = _w32_get_argv0 ();
+
+    p = strrchr (path, '/');            /* djgpp */
+    if (!p)
+      p = strrchr (path, '\\');          /* others */
+    assert (p);
+
+    if (!p || !asprintf(&home,"%.*s", (int)(p - path), path))
+      return NULL;
+
 #elif !defined(WINDOWS)
-          /* If HOME is not defined, try getting it from the password
+    /* If HOME is not defined, try getting it from the password
              file.  */
-          struct passwd *pwd = getpwuid (getuid ());
-          if (!pwd || !pwd->pw_dir)
-            return NULL;
-          home = pwd->pw_dir;
+	size_t homelen;
+    struct passwd *pwd = getpwuid (getuid ());
+    if (!pwd || !pwd->pw_dir)
+      return NULL;
+    home = xstrdup(pwd->pw_dir);
+
+	/* moved from setval_internal_tilde() - do we need it ? */
+	homelen = strlen (home);
+    while (homelen && ISSEP (home[homelen - 1]))
+      home[--homelen] = '\0';
 #else  /* !WINDOWS */
-          /* Under Windows, if $HOME isn't defined, use the directory where
-             `wget.exe' resides.  */
-          home = ws_mypath ();
+    /* Under Windows, if $HOME isn't defined, use the directory where
+       `wget.exe' resides.  */
+    home = ws_mypath ();
 #endif /* WINDOWS */
-        }
-    }
-
-  ret = home ? xstrdup (home) : NULL;
-  if (buf)
-    free (buf);
-
-  return ret;
+  }
+
+  return home;
 }
 
 /* Check the 'WGETRC' environment variable and return the file name
@@ -474,7 +473,7 @@
 char *
 wgetrc_user_file_name (void)
 {
-  char *home;
+  const char *home;
   char *file = NULL;
   /* If that failed, try $HOME/.wgetrc (or equivalent).  */
 
@@ -484,7 +483,6 @@
   home = home_dir ();
   if (home)
     file = aprintf ("%s/.wgetrc", home);
-  xfree_null (home);
 #endif /* def __VMS [else] */
 
   if (!file)
@@ -521,7 +519,6 @@
       char *home = home_dir ();
       xfree_null (file);
       file = NULL;
-      home = ws_mypath ();
       if (home)
         {
           file = aprintf ("%s/wget.ini", home);
@@ -530,7 +527,6 @@
               xfree (file);
               file = NULL;
             }
-          xfree (home);
         }
     }
 #endif /* WINDOWS */
@@ -761,12 +757,6 @@
   return line_ok;
 }
 
-#if defined(WINDOWS) || defined(MSDOS)
-# define ISSEP(c) ((c) == '/' || (c) == '\\')
-#else
-# define ISSEP(c) ((c) == '/')
-#endif
-
 /* Run commands[comind].action. */
 
 static bool
@@ -781,8 +771,7 @@
 setval_internal_tilde (int comind, const char *com, const char *val)
 {
   bool ret;
-  int homelen;
-  char *home;
+  const char *home;
   char **pstring;
   ret = setval_internal (comind, com, val);
 
@@ -795,10 +784,6 @@
       home = home_dir ();
       if (home)
 	{
-	  homelen = strlen (home);
-	  while (homelen && ISSEP (home[homelen - 1]))
-            home[--homelen] = '\0';
-
 	  /* Skip the leading "~/". */
 	  for (++val; ISSEP (*val); val++)
   	    ;

=== modified file 'src/init.h'
--- src/init.h	2011-01-01 12:19:37 +0000
+++ src/init.h	2012-04-12 10:20:54 +0000
@@ -38,7 +38,7 @@
 void initialize (void);
 void run_command (const char *);
 void setoptval (const char *, const char *, const char *);
-char *home_dir (void);
+const char *home_dir (void);
 void cleanup (void);
 void defaults (void);
 bool run_wgetrc (const char *file);

=== modified file 'src/netrc.c'
--- src/netrc.c	2011-01-01 12:19:37 +0000
+++ src/netrc.c	2012-04-12 11:05:56 +0000
@@ -81,7 +81,7 @@
 
 #else /* def __VMS */
 
-      char *home = home_dir ();
+      const char *home = home_dir ();
 
       netrc_list = NULL;
       processed_netrc = 1;
@@ -92,7 +92,6 @@
           char *path = (char *)alloca (strlen (home) + 1
                                        + strlen (NETRC_FILE_NAME) + 1);
           sprintf (path, "%s/%s", home, NETRC_FILE_NAME);
-          xfree (home);
           err = stat (path, &buf);
           if (err == 0)
             netrc_list = parse_netrc (path);

Reply via email to