We track the shstrtab and symtab section names in case they need to be
renamed. These names are sometimes assigned a static string (from the
shstrtab string pool), sometimes created as a copy of an existing
string name and sometimes created by constructing a new string. This
means they might leak because they are never freed.

Fix this leak by defining the variables early (as NULL) before looping
over all sections, making sure to always assign a allocated (copy) of
the (new) name and explicitly free them at cleanup (run both on
success and failure).

This makes it easier to reason about allocation status and string
"ownership" making it easy to see there are no memory issues even in
the rare case of a .[z]debug section being used as a symtab or
shstrtab table (which is why there is no testcase, because it is
questionable whether such a file is actually valid).

        * src/elfcompress.c (process_file): Define shstrtab_name,
        shstrtab_newname, symtab_name and symtab_newname
        early. xstrdup shstrtab_name and symtab_name if they were
        assigned to a static string. Free all four strings at
        cleanup.

Signed-off-by: Mark Wielaard <[email protected]>
---
 src/elfcompress.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/src/elfcompress.c b/src/elfcompress.c
index 789bcb383786..6f21e7c330b8 100644
--- a/src/elfcompress.c
+++ b/src/elfcompress.c
@@ -357,6 +357,12 @@ process_file (const char *fname)
   /* Which sections match and need to be (un)compressed.  */
   unsigned int *sections = NULL;
 
+  /* Specific section names when renaming shstrtab or symtab.  */
+  char *shstrtab_name = NULL;
+  char *shstrtab_newname = NULL;
+  char *symtab_name = NULL;
+  char *symtab_newname = NULL;
+
   /* How many sections are we talking about?  */
   size_t shnum = 0;
   int res = 1;
@@ -703,12 +709,8 @@ process_file (const char *fname)
      difference later when we do compress.  */
   enum ch_type shstrtab_compressed = UNSET;
   size_t shstrtab_size = 0;
-  char *shstrtab_name = NULL;
-  char *shstrtab_newname = NULL;
   enum ch_type symtab_compressed = UNSET;
   size_t symtab_size = 0;
-  char *symtab_name = NULL;
-  char *symtab_newname = NULL;
 
   /* Collection pass.  Copy over the sections, (de)compresses matching
      sections, collect names of sections and symbol table if
@@ -1141,6 +1143,7 @@ process_file (const char *fname)
                     shdrstrndx);
              goto cleanup;
            }
+         shstrtab_name = xstrdup (shstrtab_name);
 
          shstrtab_size = shdr->sh_size;
          if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
@@ -1282,6 +1285,7 @@ process_file (const char *fname)
                             symtabndx);
                      goto cleanup;
                    }
+                 symtab_name = xstrdup (symtab_name);
 
                  symtab_size = shdr->sh_size;
                  if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
@@ -1396,6 +1400,10 @@ cleanup:
     }
 
   free (sections);
+  free (shstrtab_name);
+  free (shstrtab_newname);
+  free (symtab_name);
+  free (symtab_newname);
   return res;
 }
 
-- 
2.54.0

Reply via email to