Subject: bug#47383: [PATCH 2/2] ln: fix memory leaks in do_link()

From: Kamil Dudka <[email-masked]>
Date: Thu, 25 Mar 2021 11:57:56 +0100

* src/ln.c (do_link): Free memory allocated by convert_abs_rel()
on all code paths.
---
 src/ln.c | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/src/ln.c b/src/ln.c
index e79ca5e7ade..368b109daf0 100644
--- a/src/ln.c
+++ b/src/ln.c
@@ -229,14 +229,14 @@ do_link (char const *source, int destdir_fd, char const *dest_base,
               if (errno != ENOENT)
                 {
                   error (0, errno, _("failed to access %s"), quoteaf (dest));
-                  return false;
+                  goto fail;
                 }
               force = false;
             }
           else if (S_ISDIR (dest_stats.st_mode))
             {
               error (0, 0, _("%s: cannot overwrite directory"), quotef (dest));
-              return false;
+              goto fail;
             }
           else if (seen_file (dest_set, dest, &dest_stats))
             {
@@ -245,7 +245,7 @@ do_link (char const *source, int destdir_fd, char const *dest_base,
               error (0, 0,
                      _("will not overwrite just-created %s with %s"),
                      quoteaf_n (0, dest), quoteaf_n (1, source));
-              return false;
+              goto fail;
             }
           else
             {
@@ -274,7 +274,7 @@ do_link (char const *source, int destdir_fd, char const *dest_base,
                     {
                       error (0, 0, _("%s and %s are the same file"),
                              quoteaf_n (0, source), quoteaf_n (1, dest));
-                      return false;
+                      goto fail;
                     }
                 }
 
@@ -285,7 +285,10 @@ do_link (char const *source, int destdir_fd, char const *dest_base,
                       fprintf (stderr, _("%s: replace %s? "),
                                program_name, quoteaf (dest));
                       if (!yesno ())
-                        return true;
+                        {
+                          free(rel_source);
+                          return true;
+                        }
                     }
 
                   if (backup_type != no_backups)
@@ -304,7 +307,7 @@ do_link (char const *source, int destdir_fd, char const *dest_base,
                            {
                               error (0, rename_errno, _("cannot backup %s"),
                                      quoteaf (dest));
-                              return false;
+                              goto fail;
                             }
                           force = false;
                         }
@@ -397,6 +400,10 @@ do_link (char const *source, int destdir_fd, char const *dest_base,
   free (backup_base);
   free (rel_source);
   return link_errno <= 0;
+
+fail:
+  free (rel_source);
+  return false;
 }
 
 void
-- 
2.26.3