diff mbox series

elfload: use g_new instead of malloc

Message ID 20201001123807.42978-1-eafanasova@gmail.com
State New
Headers show
Series elfload: use g_new instead of malloc | expand

Commit Message

Elena Afanasova Oct. 1, 2020, 12:38 p.m. UTC
Signed-off-by: Elena Afanasova <eafanasova@gmail.com>
---
 bsd-user/elfload.c | 92 +++++++++++++++-------------------------------
 1 file changed, 30 insertions(+), 62 deletions(-)

Comments

Thomas Huth Oct. 1, 2020, 3:01 p.m. UTC | #1
On 01/10/2020 14.38, Elena Afanasova wrote:
> Signed-off-by: Elena Afanasova <eafanasova@gmail.com>

> ---

>  bsd-user/elfload.c | 92 +++++++++++++++-------------------------------

>  1 file changed, 30 insertions(+), 62 deletions(-)

> 

> diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c

> index 32378af7b2..e10ca54eb7 100644

> --- a/bsd-user/elfload.c

> +++ b/bsd-user/elfload.c

> @@ -867,18 +867,14 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,

>          if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE)

>              return ~(abi_ulong)0UL;

>  

> -        elf_phdata =  (struct elf_phdr *)

> -                malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);

> -

> -        if (!elf_phdata)

> -          return ~((abi_ulong)0UL);

> +        elf_phdata = g_new(struct elf_phdr, interp_elf_ex->e_phnum);

>  

>          /*

>           * If the size of this structure has changed, then punt, since

>           * we will be doing the wrong thing.

>           */

>          if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) {

> -            free(elf_phdata);

> +            g_free(elf_phdata);

>              return ~((abi_ulong)0UL);

>          }

>  

> @@ -890,9 +886,8 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,

>          }

>          if (retval < 0) {

>                  perror("load_elf_interp");

> +                g_free(elf_phdata);

>                  exit(-1);

> -                free (elf_phdata);

> -                return retval;

>          }

>  #ifdef BSWAP_NEEDED

>          eppnt = elf_phdata;

> @@ -940,7 +935,7 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,

>              if (error == -1) {

>                /* Real error */

>                close(interpreter_fd);

> -              free(elf_phdata);

> +              g_free(elf_phdata);

>                return ~((abi_ulong)0UL);

>              }

>  

> @@ -983,7 +978,7 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,

>                          PROT_READ|PROT_WRITE|PROT_EXEC,

>                          MAP_FIXED|MAP_PRIVATE|MAP_ANON, -1, 0);

>          }

> -        free(elf_phdata);

> +        g_free(elf_phdata);

>  

>          *interp_load_addr = load_addr;

>          return ((abi_ulong) interp_elf_ex->e_entry) + load_addr;

> @@ -1064,24 +1059,15 @@ static void load_symbols(struct elfhdr *hdr, int fd)

>  

>   found:

>      /* Now know where the strtab and symtab are.  Snarf them. */

> -    s = malloc(sizeof(*s));

> -    syms = malloc(symtab.sh_size);

> -    if (!syms) {

> -        free(s);

> -        return;

> -    }

> -    s->disas_strtab = strings = malloc(strtab.sh_size);

> -    if (!s->disas_strtab) {

> -        free(s);

> -        free(syms);

> -        return;

> -    }

> +    s = g_new(struct syminfo, 1);

> +    syms = g_new(symtab.sh_size, 1);

> +    s->disas_strtab = strings = g_new(strtab.sh_size, 1);

>  

>      lseek(fd, symtab.sh_offset, SEEK_SET);

>      if (read(fd, syms, symtab.sh_size) != symtab.sh_size) {

> -        free(s);

> -        free(syms);

> -        free(strings);

> +        g_free(s);

> +        g_free(syms);

> +        g_free(strings);

>          return;

>      }

>  

> @@ -1113,22 +1099,16 @@ static void load_symbols(struct elfhdr *hdr, int fd)

>          that we threw away.  Whether or not this has any effect on the

>          memory allocation depends on the malloc implementation and how

>          many symbols we managed to discard. */

> -    new_syms = realloc(syms, nsyms * sizeof(*syms));

> -    if (new_syms == NULL) {

> -        free(s);

> -        free(syms);

> -        free(strings);

> -        return;

> -    }

> +    new_syms = g_realloc(syms, nsyms * sizeof(*syms));

>      syms = new_syms;

>  

>      qsort(syms, nsyms, sizeof(*syms), symcmp);

>  

>      lseek(fd, strtab.sh_offset, SEEK_SET);

>      if (read(fd, strings, strtab.sh_size) != strtab.sh_size) {

> -        free(s);

> -        free(syms);

> -        free(strings);

> +        g_free(s);

> +        g_free(syms);

> +        g_free(strings);

>          return;

>      }

[...]

 Hi!

That clean-up sounds like a very good idea ... but I think this would be
a perfect place to use g_autofree in the declaration of the variables,
then you can get rid of the free() calls completely!

 Thomas
Markus Armbruster Oct. 2, 2020, 5:05 a.m. UTC | #2
Elena Afanasova <eafanasova@gmail.com> writes:

> Signed-off-by: Elena Afanasova <eafanasova@gmail.com>

> ---

>  bsd-user/elfload.c | 92 +++++++++++++++-------------------------------

>  1 file changed, 30 insertions(+), 62 deletions(-)

>

> diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c

> index 32378af7b2..e10ca54eb7 100644

> --- a/bsd-user/elfload.c

> +++ b/bsd-user/elfload.c

> @@ -867,18 +867,14 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,

>          if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE)

>              return ~(abi_ulong)0UL;

>  

> -        elf_phdata =  (struct elf_phdr *)

> -                malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);

> -

> -        if (!elf_phdata)

> -          return ~((abi_ulong)0UL);

> +        elf_phdata = g_new(struct elf_phdr, interp_elf_ex->e_phnum);

>  

>          /*

>           * If the size of this structure has changed, then punt, since

>           * we will be doing the wrong thing.

>           */

>          if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) {

> -            free(elf_phdata);

> +            g_free(elf_phdata);

>              return ~((abi_ulong)0UL);

>          }

>  

> @@ -890,9 +886,8 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,

>          }

>          if (retval < 0) {

>                  perror("load_elf_interp");

> +                g_free(elf_phdata);

>                  exit(-1);

> -                free (elf_phdata);

> -                return retval;


Deleting return looks wrong.

>          }

>  #ifdef BSWAP_NEEDED

>          eppnt = elf_phdata;

> @@ -940,7 +935,7 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,

>              if (error == -1) {

>                /* Real error */

>                close(interpreter_fd);

> -              free(elf_phdata);

> +              g_free(elf_phdata);

>                return ~((abi_ulong)0UL);

>              }

>  

> @@ -983,7 +978,7 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,

>                          PROT_READ|PROT_WRITE|PROT_EXEC,

>                          MAP_FIXED|MAP_PRIVATE|MAP_ANON, -1, 0);

>          }

> -        free(elf_phdata);

> +        g_free(elf_phdata);

>  

>          *interp_load_addr = load_addr;

>          return ((abi_ulong) interp_elf_ex->e_entry) + load_addr;

> @@ -1064,24 +1059,15 @@ static void load_symbols(struct elfhdr *hdr, int fd)

>  

>   found:

>      /* Now know where the strtab and symtab are.  Snarf them. */

> -    s = malloc(sizeof(*s));

> -    syms = malloc(symtab.sh_size);

> -    if (!syms) {

> -        free(s);

> -        return;

> -    }

> -    s->disas_strtab = strings = malloc(strtab.sh_size);

> -    if (!s->disas_strtab) {

> -        free(s);

> -        free(syms);

> -        return;

> -    }

> +    s = g_new(struct syminfo, 1);

> +    syms = g_new(symtab.sh_size, 1);


g_new() takes a struct type argument, symtab.sh_size is an expression.
I'm pretty sure this doesn't even compile.

I'm looking no further.

Nacked-by: Markus Armbruster <armbru@redhat.com>


[...]
Thomas Huth Oct. 2, 2020, 5:18 a.m. UTC | #3
On 02/10/2020 07.05, Markus Armbruster wrote:
> Elena Afanasova <eafanasova@gmail.com> writes:

> 

>> Signed-off-by: Elena Afanasova <eafanasova@gmail.com>

>> ---

>>  bsd-user/elfload.c | 92 +++++++++++++++-------------------------------

>>  1 file changed, 30 insertions(+), 62 deletions(-)

>>

>> diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c

>> index 32378af7b2..e10ca54eb7 100644

>> --- a/bsd-user/elfload.c

>> +++ b/bsd-user/elfload.c

>> @@ -867,18 +867,14 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,

>>          if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE)

>>              return ~(abi_ulong)0UL;

>>  

>> -        elf_phdata =  (struct elf_phdr *)

>> -                malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);

>> -

>> -        if (!elf_phdata)

>> -          return ~((abi_ulong)0UL);

>> +        elf_phdata = g_new(struct elf_phdr, interp_elf_ex->e_phnum);

>>  

>>          /*

>>           * If the size of this structure has changed, then punt, since

>>           * we will be doing the wrong thing.

>>           */

>>          if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) {

>> -            free(elf_phdata);

>> +            g_free(elf_phdata);

>>              return ~((abi_ulong)0UL);

>>          }

>>  

>> @@ -890,9 +886,8 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,

>>          }

>>          if (retval < 0) {

>>                  perror("load_elf_interp");

>> +                g_free(elf_phdata);

>>                  exit(-1);

>> -                free (elf_phdata);

>> -                return retval;

> 

> Deleting return looks wrong.


Why? There is an exit(-1) right in front of it, so this is dead code...
well, maybe that should be done in a separate patch, or at least
mentioned in the patch description, though.

 Thomas
Markus Armbruster Oct. 2, 2020, 8:58 a.m. UTC | #4
Thomas Huth <thuth@redhat.com> writes:

> On 02/10/2020 07.05, Markus Armbruster wrote:

>> Elena Afanasova <eafanasova@gmail.com> writes:

>> 

>>> Signed-off-by: Elena Afanasova <eafanasova@gmail.com>

>>> ---

>>>  bsd-user/elfload.c | 92 +++++++++++++++-------------------------------

>>>  1 file changed, 30 insertions(+), 62 deletions(-)

>>>

>>> diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c

>>> index 32378af7b2..e10ca54eb7 100644

>>> --- a/bsd-user/elfload.c

>>> +++ b/bsd-user/elfload.c

>>> @@ -867,18 +867,14 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,

>>>          if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE)

>>>              return ~(abi_ulong)0UL;

>>>  

>>> -        elf_phdata =  (struct elf_phdr *)

>>> -                malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);

>>> -

>>> -        if (!elf_phdata)

>>> -          return ~((abi_ulong)0UL);

>>> +        elf_phdata = g_new(struct elf_phdr, interp_elf_ex->e_phnum);

>>>  

>>>          /*

>>>           * If the size of this structure has changed, then punt, since

>>>           * we will be doing the wrong thing.

>>>           */

>>>          if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) {

>>> -            free(elf_phdata);

>>> +            g_free(elf_phdata);

>>>              return ~((abi_ulong)0UL);

>>>          }

>>>  

>>> @@ -890,9 +886,8 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,

>>>          }

>>>          if (retval < 0) {

>>>                  perror("load_elf_interp");

>>> +                g_free(elf_phdata);

>>>                  exit(-1);

>>> -                free (elf_phdata);

>>> -                return retval;

>> 

>> Deleting return looks wrong.

>

> Why? There is an exit(-1) right in front of it, so this is dead code...

> well, maybe that should be done in a separate patch, or at least

> mentioned in the patch description, though.


You're right; I missed the exit(-1).

Following the unpleasant odour spread by exit(-1)...  Aha, the
function's behavior on error is inconsistent: sometimes it returns zero,
sometimes it exits.

Since the problem is bigger than just one dead return, I recommend
leaving it to a separate patch, and keeping this one focused on g_new().
Eric Blake Oct. 2, 2020, 3:08 p.m. UTC | #5
On 10/2/20 3:58 AM, Markus Armbruster wrote:

>>>> @@ -890,9 +886,8 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,

>>>>          }

>>>>          if (retval < 0) {

>>>>                  perror("load_elf_interp");

>>>> +                g_free(elf_phdata);

>>>>                  exit(-1);

>>>> -                free (elf_phdata);

>>>> -                return retval;

>>>

>>> Deleting return looks wrong.

>>

>> Why? There is an exit(-1) right in front of it, so this is dead code...

>> well, maybe that should be done in a separate patch, or at least

>> mentioned in the patch description, though.

> 

> You're right; I missed the exit(-1).

> 

> Following the unpleasant odour spread by exit(-1)...  Aha, the

> function's behavior on error is inconsistent: sometimes it returns zero,

> sometimes it exits.


Eradicating exit(-1) (which is indistinguishable from exit(255), and
generally not what you want, unless your program is designed to
specifically invoke the immediate-exit semantics of xargs) is also a
worthwhile cleanup project.  But I agree with the advice for separate
patches for separate bugs.

> 

> Since the problem is bigger than just one dead return, I recommend

> leaving it to a separate patch, and keeping this one focused on g_new().

> 

> 


-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3226
Virtualization:  qemu.org | libvirt.org
Elena Afanasova Oct. 4, 2020, 12:20 p.m. UTC | #6
Subject: [PATCH v2] elfload: use g_new/g_malloc and g_autofree

Signed-off-by: Elena Afanasova <eafanasova@gmail.com>

---
 bsd-user/elfload.c | 79 ++++++++--------------------------------------
 1 file changed, 14 insertions(+), 65 deletions(-)

diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c
index 32378af7b2..bc4be4c874 100644
--- a/bsd-user/elfload.c
+++ b/bsd-user/elfload.c
@@ -838,7 +838,7 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
                                  int interpreter_fd,
                                  abi_ulong *interp_load_addr)
 {
-        struct elf_phdr *elf_phdata  =  NULL;
+        g_autofree struct elf_phdr *elf_phdata = NULL;
         struct elf_phdr *eppnt;
         abi_ulong load_addr = 0;
         int load_addr_set = 0;
@@ -867,18 +867,13 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
         if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE)
             return ~(abi_ulong)0UL;
 
-        elf_phdata =  (struct elf_phdr *)
-                malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
-
-        if (!elf_phdata)
-          return ~((abi_ulong)0UL);
+        elf_phdata = g_new(struct elf_phdr, interp_elf_ex->e_phnum);
 
         /*
          * If the size of this structure has changed, then punt, since
          * we will be doing the wrong thing.
          */
         if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) {
-            free(elf_phdata);
             return ~((abi_ulong)0UL);
         }
 
@@ -891,7 +886,6 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
         if (retval < 0) {
                 perror("load_elf_interp");
                 exit(-1);
-                free (elf_phdata);
                 return retval;
         }
 #ifdef BSWAP_NEEDED
@@ -940,7 +934,6 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
             if (error == -1) {
               /* Real error */
               close(interpreter_fd);
-              free(elf_phdata);
               return ~((abi_ulong)0UL);
             }
 
@@ -983,7 +976,6 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
                         PROT_READ|PROT_WRITE|PROT_EXEC,
                         MAP_FIXED|MAP_PRIVATE|MAP_ANON, -1, 0);
         }
-        free(elf_phdata);
 
         *interp_load_addr = load_addr;
         return ((abi_ulong) interp_elf_ex->e_entry) + load_addr;
@@ -1036,9 +1028,10 @@ static void load_symbols(struct elfhdr *hdr, int fd)
 {
     unsigned int i, nsyms;
     struct elf_shdr sechdr, symtab, strtab;
-    char *strings;
-    struct syminfo *s;
-    struct elf_sym *syms, *new_syms;
+    g_autofree char *strings = NULL;
+    g_autofree struct syminfo *s = NULL;
+    g_autofree struct elf_sym *syms = NULL;
+    struct elf_sym *new_syms;
 
     lseek(fd, hdr->e_shoff, SEEK_SET);
     for (i = 0; i < hdr->e_shnum; i++) {
@@ -1064,24 +1057,12 @@ static void load_symbols(struct elfhdr *hdr, int fd)
 
  found:
     /* Now know where the strtab and symtab are.  Snarf them. */
-    s = malloc(sizeof(*s));
-    syms = malloc(symtab.sh_size);
-    if (!syms) {
-        free(s);
-        return;
-    }
-    s->disas_strtab = strings = malloc(strtab.sh_size);
-    if (!s->disas_strtab) {
-        free(s);
-        free(syms);
-        return;
-    }
+    s = g_new(struct syminfo, 1);
+    syms = g_malloc(symtab.sh_size);
+    s->disas_strtab = strings = g_new(char, strtab.sh_size);
 
     lseek(fd, symtab.sh_offset, SEEK_SET);
     if (read(fd, syms, symtab.sh_size) != symtab.sh_size) {
-        free(s);
-        free(syms);
-        free(strings);
         return;
     }
 
@@ -1113,22 +1094,13 @@ static void load_symbols(struct elfhdr *hdr, int fd)
         that we threw away.  Whether or not this has any effect on the
         memory allocation depends on the malloc implementation and how
         many symbols we managed to discard. */
-    new_syms = realloc(syms, nsyms * sizeof(*syms));
-    if (new_syms == NULL) {
-        free(s);
-        free(syms);
-        free(strings);
-        return;
-    }
+    new_syms = g_realloc(syms, nsyms * sizeof(*syms));
     syms = new_syms;
 
     qsort(syms, nsyms, sizeof(*syms), symcmp);
 
     lseek(fd, strtab.sh_offset, SEEK_SET);
     if (read(fd, strings, strtab.sh_size) != strtab.sh_size) {
-        free(s);
-        free(syms);
-        free(strings);
         return;
     }
     s->disas_num_syms = nsyms;
@@ -1156,10 +1128,10 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     unsigned char ibcs2_interpreter;
     int i;
     struct elf_phdr * elf_ppnt;
-    struct elf_phdr *elf_phdata;
+    g_autofree struct elf_phdr *elf_phdata = NULL;
     abi_ulong elf_bss, k, elf_brk;
     int retval;
-    char * elf_interpreter;
+    g_autofree char *elf_interpreter = NULL;
     abi_ulong elf_entry, interp_load_addr = 0;
     abi_ulong start_code, end_code, start_data, end_data;
     abi_ulong reloc_func_desc = 0;
@@ -1190,10 +1162,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     }
 
     /* Now read in all of the header information */
-    elf_phdata = (struct elf_phdr *)malloc(elf_ex.e_phentsize*elf_ex.e_phnum);
-    if (elf_phdata == NULL) {
-        return -ENOMEM;
-    }
+    elf_phdata = g_new(struct elf_phdr, elf_ex.e_phnum);
 
     retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET);
     if(retval > 0) {
@@ -1204,7 +1173,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     if (retval < 0) {
         perror("load_elf_binary");
         exit(-1);
-        free (elf_phdata);
         return -errno;
     }
 
@@ -1220,7 +1188,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     elf_brk = 0;
 
 
-    elf_interpreter = NULL;
     start_code = ~((abi_ulong)0UL);
     end_code = 0;
     start_data = 0;
@@ -1231,8 +1198,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
         if (elf_ppnt->p_type == PT_INTERP) {
             if ( elf_interpreter != NULL )
             {
-                free (elf_phdata);
-                free(elf_interpreter);
                 close(bprm->fd);
                 return -EINVAL;
             }
@@ -1242,13 +1207,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
              * is an a.out format binary
              */
 
-            elf_interpreter = (char *)malloc(elf_ppnt->p_filesz);
-
-            if (elf_interpreter == NULL) {
-                free (elf_phdata);
-                close(bprm->fd);
-                return -ENOMEM;
-            }
+            elf_interpreter = g_new(char, elf_ppnt->p_filesz);
 
             retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET);
             if(retval >= 0) {
@@ -1298,8 +1257,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
             if (retval < 0) {
                 perror("load_elf_binary3");
                 exit(-1);
-                free (elf_phdata);
-                free(elf_interpreter);
                 close(bprm->fd);
                 return retval;
             }
@@ -1323,8 +1280,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
         }
 
         if (!interpreter_type) {
-            free(elf_interpreter);
-            free(elf_phdata);
             close(bprm->fd);
             return -ELIBBAD;
         }
@@ -1346,8 +1301,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
             }
         }
         if (!bprm->p) {
-            free(elf_interpreter);
-            free (elf_phdata);
             close(bprm->fd);
             return -E2BIG;
         }
@@ -1486,18 +1439,14 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
         reloc_func_desc = interp_load_addr;
 
         close(interpreter_fd);
-        free(elf_interpreter);
 
         if (elf_entry == ~((abi_ulong)0UL)) {
             printf("Unable to load interpreter\n");
-            free(elf_phdata);
             exit(-1);
             return 0;
         }
     }
 
-    free(elf_phdata);
-
     if (qemu_log_enabled())
         load_symbols(&elf_ex, bprm->fd);
 
-- 
2.25.1

On Fri, 2020-10-02 at 10:08 -0500, Eric Blake wrote:
> On 10/2/20 3:58 AM, Markus Armbruster wrote:

> 

> > > > > @@ -890,9 +886,8 @@ static abi_ulong load_elf_interp(struct

> > > > > elfhdr * interp_elf_ex,

> > > > >          }

> > > > >          if (retval < 0) {

> > > > >                  perror("load_elf_interp");

> > > > > +                g_free(elf_phdata);

> > > > >                  exit(-1);

> > > > > -                free (elf_phdata);

> > > > > -                return retval;

> > > > 

> > > > Deleting return looks wrong.

> > > 

> > > Why? There is an exit(-1) right in front of it, so this is dead

> > > code...

> > > well, maybe that should be done in a separate patch, or at least

> > > mentioned in the patch description, though.

> > 

> > You're right; I missed the exit(-1).

> > 

> > Following the unpleasant odour spread by exit(-1)...  Aha, the

> > function's behavior on error is inconsistent: sometimes it returns

> > zero,

> > sometimes it exits.

> 

> Eradicating exit(-1) (which is indistinguishable from exit(255), and

> generally not what you want, unless your program is designed to

> specifically invoke the immediate-exit semantics of xargs) is also a

> worthwhile cleanup project.  But I agree with the advice for separate

> patches for separate bugs.

> 

> > Since the problem is bigger than just one dead return, I recommend

> > leaving it to a separate patch, and keeping this one focused on

> > g_new().

> > 

> >
Markus Armbruster Oct. 5, 2020, 7:57 a.m. UTC | #7
Please don't post respins as replies, because our tooling will miss them
there, and even humans may.  Start a new thread instead.  Next time :)

Elena Afanasova <eafanasova@gmail.com> writes:

> Subject: [PATCH v2] elfload: use g_new/g_malloc and g_autofree

>

> Signed-off-by: Elena Afanasova <eafanasova@gmail.com>

> ---

>  bsd-user/elfload.c | 79 ++++++++--------------------------------------

>  1 file changed, 14 insertions(+), 65 deletions(-)

>

> diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c

> index 32378af7b2..bc4be4c874 100644

> --- a/bsd-user/elfload.c

> +++ b/bsd-user/elfload.c

> @@ -838,7 +838,7 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,

>                                   int interpreter_fd,

>                                   abi_ulong *interp_load_addr)

>  {

> -        struct elf_phdr *elf_phdata  =  NULL;

> +        g_autofree struct elf_phdr *elf_phdata = NULL;

>          struct elf_phdr *eppnt;

>          abi_ulong load_addr = 0;

>          int load_addr_set = 0;

> @@ -867,18 +867,13 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,

>          if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE)

>              return ~(abi_ulong)0UL;

>  

> -        elf_phdata =  (struct elf_phdr *)

> -                malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);

> -

> -        if (!elf_phdata)

> -          return ~((abi_ulong)0UL);

> +        elf_phdata = g_new(struct elf_phdr, interp_elf_ex->e_phnum);

>  

>          /*

>           * If the size of this structure has changed, then punt, since

>           * we will be doing the wrong thing.

>           */

>          if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) {

> -            free(elf_phdata);

>              return ~((abi_ulong)0UL);

>          }

>  

> @@ -891,7 +886,6 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,

>          if (retval < 0) {

>                  perror("load_elf_interp");

>                  exit(-1);

> -                free (elf_phdata);

>                  return retval;

>          }

>  #ifdef BSWAP_NEEDED

> @@ -940,7 +934,6 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,

>              if (error == -1) {

>                /* Real error */

>                close(interpreter_fd);

> -              free(elf_phdata);

>                return ~((abi_ulong)0UL);

>              }

>  

> @@ -983,7 +976,6 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,

>                          PROT_READ|PROT_WRITE|PROT_EXEC,

>                          MAP_FIXED|MAP_PRIVATE|MAP_ANON, -1, 0);

>          }

> -        free(elf_phdata);

>  

>          *interp_load_addr = load_addr;

>          return ((abi_ulong) interp_elf_ex->e_entry) + load_addr;

> @@ -1036,9 +1028,10 @@ static void load_symbols(struct elfhdr *hdr, int fd)

>  {

>      unsigned int i, nsyms;

>      struct elf_shdr sechdr, symtab, strtab;

> -    char *strings;

> -    struct syminfo *s;

> -    struct elf_sym *syms, *new_syms;

> +    g_autofree char *strings = NULL;

> +    g_autofree struct syminfo *s = NULL;

> +    g_autofree struct elf_sym *syms = NULL;

> +    struct elf_sym *new_syms;


Note for later: @strings, @syminfo and @syms are freed on return.

>  

>      lseek(fd, hdr->e_shoff, SEEK_SET);

>      for (i = 0; i < hdr->e_shnum; i++) {

> @@ -1064,24 +1057,12 @@ static void load_symbols(struct elfhdr *hdr, int fd)

>  

>   found:

>      /* Now know where the strtab and symtab are.  Snarf them. */

> -    s = malloc(sizeof(*s));

> -    syms = malloc(symtab.sh_size);

> -    if (!syms) {

> -        free(s);

> -        return;

> -    }

> -    s->disas_strtab = strings = malloc(strtab.sh_size);

> -    if (!s->disas_strtab) {

> -        free(s);

> -        free(syms);

> -        return;

> -    }

> +    s = g_new(struct syminfo, 1);


The smaller change would be

       s = g_malloc(sizeof(*s));

Matter of taste.

> +    syms = g_malloc(symtab.sh_size);

> +    s->disas_strtab = strings = g_new(char, strtab.sh_size);


I'd prefer the simpler

       s->disas_strtab = strings = g_malloc(strtab.sh_size);

Yes, it returns void * whereas g_new() returns char *, but the char * is
vanishingly unlikely to catch actual bugs.

>  

>      lseek(fd, symtab.sh_offset, SEEK_SET);

>      if (read(fd, syms, symtab.sh_size) != symtab.sh_size) {

> -        free(s);

> -        free(syms);

> -        free(strings);

>          return;

>      }

>  

> @@ -1113,22 +1094,13 @@ static void load_symbols(struct elfhdr *hdr, int fd)

>          that we threw away.  Whether or not this has any effect on the

>          memory allocation depends on the malloc implementation and how

>          many symbols we managed to discard. */

> -    new_syms = realloc(syms, nsyms * sizeof(*syms));

> -    if (new_syms == NULL) {

> -        free(s);

> -        free(syms);

> -        free(strings);

> -        return;

> -    }

> +    new_syms = g_realloc(syms, nsyms * sizeof(*syms));

>      syms = new_syms;

>  

>      qsort(syms, nsyms, sizeof(*syms), symcmp);

>  

>      lseek(fd, strtab.sh_offset, SEEK_SET);

>      if (read(fd, strings, strtab.sh_size) != strtab.sh_size) {

> -        free(s);

> -        free(syms);

> -        free(strings);

>          return;

>      }

>      s->disas_num_syms = nsyms;

   #if ELF_CLASS == ELFCLASS32
       s->disas_symtab.elf32 = syms;
       s->lookup_symbol = (lookup_symbol_t)lookup_symbolxx;
   #else
       s->disas_symtab.elf64 = syms;
       s->lookup_symbol = (lookup_symbol_t)lookup_symbolxx;
   #endif
       s->next = syminfos;
       syminfos = s;

@strings, @syminfo and @syms are freed here.  s->disas_strtab,
s->disas_symtab.elf{32,64}, s->next become dangling pointers.
I'd expect this to blow up.  Have you tested?

   }

> @@ -1156,10 +1128,10 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,

>      unsigned char ibcs2_interpreter;

>      int i;

>      struct elf_phdr * elf_ppnt;

> -    struct elf_phdr *elf_phdata;

> +    g_autofree struct elf_phdr *elf_phdata = NULL;

>      abi_ulong elf_bss, k, elf_brk;

>      int retval;

> -    char * elf_interpreter;

> +    g_autofree char *elf_interpreter = NULL;

>      abi_ulong elf_entry, interp_load_addr = 0;

>      abi_ulong start_code, end_code, start_data, end_data;

>      abi_ulong reloc_func_desc = 0;

> @@ -1190,10 +1162,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,

>      }

>  

>      /* Now read in all of the header information */

> -    elf_phdata = (struct elf_phdr *)malloc(elf_ex.e_phentsize*elf_ex.e_phnum);

> -    if (elf_phdata == NULL) {

> -        return -ENOMEM;

> -    }

> +    elf_phdata = g_new(struct elf_phdr, elf_ex.e_phnum);


This assumes elf_ex.e_phentsize == sizeof(struct elf_phdr).  Why is that
true?

>  

>      retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET);

>      if(retval > 0) {

> @@ -1204,7 +1173,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,

>      if (retval < 0) {

>          perror("load_elf_binary");

>          exit(-1);

> -        free (elf_phdata);

>          return -errno;

>      }

>  

> @@ -1220,7 +1188,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,

>      elf_brk = 0;

>  

>  

> -    elf_interpreter = NULL;

>      start_code = ~((abi_ulong)0UL);

>      end_code = 0;

>      start_data = 0;

> @@ -1231,8 +1198,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,

>          if (elf_ppnt->p_type == PT_INTERP) {

>              if ( elf_interpreter != NULL )

>              {

> -                free (elf_phdata);

> -                free(elf_interpreter);

>                  close(bprm->fd);

>                  return -EINVAL;

>              }

> @@ -1242,13 +1207,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,

>               * is an a.out format binary

>               */

>  

> -            elf_interpreter = (char *)malloc(elf_ppnt->p_filesz);

> -

> -            if (elf_interpreter == NULL) {

> -                free (elf_phdata);

> -                close(bprm->fd);

> -                return -ENOMEM;

> -            }

> +            elf_interpreter = g_new(char, elf_ppnt->p_filesz);


Again, I'd prefer the simpler

               elf_interpreter = g_malloc(elf_ppnt->p_filesz);

>  

>              retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET);

>              if(retval >= 0) {

> @@ -1298,8 +1257,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,

>              if (retval < 0) {

>                  perror("load_elf_binary3");

>                  exit(-1);

> -                free (elf_phdata);

> -                free(elf_interpreter);

>                  close(bprm->fd);

>                  return retval;

>              }

> @@ -1323,8 +1280,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,

>          }

>  

>          if (!interpreter_type) {

> -            free(elf_interpreter);

> -            free(elf_phdata);

>              close(bprm->fd);

>              return -ELIBBAD;

>          }

> @@ -1346,8 +1301,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,

>              }

>          }

>          if (!bprm->p) {

> -            free(elf_interpreter);

> -            free (elf_phdata);

>              close(bprm->fd);

>              return -E2BIG;

>          }

> @@ -1486,18 +1439,14 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,

>          reloc_func_desc = interp_load_addr;

>  

>          close(interpreter_fd);

> -        free(elf_interpreter);

>  

>          if (elf_entry == ~((abi_ulong)0UL)) {

>              printf("Unable to load interpreter\n");

> -            free(elf_phdata);

>              exit(-1);

>              return 0;

>          }

>      }

>  

> -    free(elf_phdata);

> -

>      if (qemu_log_enabled())

>          load_symbols(&elf_ex, bprm->fd);
Peter Maydell Oct. 5, 2020, 9:55 a.m. UTC | #8
On Sun, 4 Oct 2020 at 13:22, Elena Afanasova <eafanasova@gmail.com> wrote:
>

> Subject: [PATCH v2] elfload: use g_new/g_malloc and g_autofree

>

> Signed-off-by: Elena Afanasova <eafanasova@gmail.com>

> ---

>  bsd-user/elfload.c | 79 ++++++++--------------------------------------

>  1 file changed, 14 insertions(+), 65 deletions(-)


Random question -- how are you testing this change? (bsd-user
isn't covered by 'make check' I think).

thanks
-- PMM
Elena Afanasova Oct. 6, 2020, 5:58 p.m. UTC | #9
Since bsd user space emulation doesn't work for me I can only use
'gmake check'... But some tests don't seem to be supported.

On Mon, 2020-10-05 at 10:55 +0100, Peter Maydell wrote:
> On Sun, 4 Oct 2020 at 13:22, Elena Afanasova <eafanasova@gmail.com>

> wrote:

> > Subject: [PATCH v2] elfload: use g_new/g_malloc and g_autofree

> > 

> > Signed-off-by: Elena Afanasova <eafanasova@gmail.com>

> > ---

> >  bsd-user/elfload.c | 79 ++++++++--------------------------------

> > ------

> >  1 file changed, 14 insertions(+), 65 deletions(-)

> 

> Random question -- how are you testing this change? (bsd-user

> isn't covered by 'make check' I think).

> 

> thanks

> -- PMM
diff mbox series

Patch

diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c
index 32378af7b2..e10ca54eb7 100644
--- a/bsd-user/elfload.c
+++ b/bsd-user/elfload.c
@@ -867,18 +867,14 @@  static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
         if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE)
             return ~(abi_ulong)0UL;
 
-        elf_phdata =  (struct elf_phdr *)
-                malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
-
-        if (!elf_phdata)
-          return ~((abi_ulong)0UL);
+        elf_phdata = g_new(struct elf_phdr, interp_elf_ex->e_phnum);
 
         /*
          * If the size of this structure has changed, then punt, since
          * we will be doing the wrong thing.
          */
         if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) {
-            free(elf_phdata);
+            g_free(elf_phdata);
             return ~((abi_ulong)0UL);
         }
 
@@ -890,9 +886,8 @@  static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
         }
         if (retval < 0) {
                 perror("load_elf_interp");
+                g_free(elf_phdata);
                 exit(-1);
-                free (elf_phdata);
-                return retval;
         }
 #ifdef BSWAP_NEEDED
         eppnt = elf_phdata;
@@ -940,7 +935,7 @@  static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
             if (error == -1) {
               /* Real error */
               close(interpreter_fd);
-              free(elf_phdata);
+              g_free(elf_phdata);
               return ~((abi_ulong)0UL);
             }
 
@@ -983,7 +978,7 @@  static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
                         PROT_READ|PROT_WRITE|PROT_EXEC,
                         MAP_FIXED|MAP_PRIVATE|MAP_ANON, -1, 0);
         }
-        free(elf_phdata);
+        g_free(elf_phdata);
 
         *interp_load_addr = load_addr;
         return ((abi_ulong) interp_elf_ex->e_entry) + load_addr;
@@ -1064,24 +1059,15 @@  static void load_symbols(struct elfhdr *hdr, int fd)
 
  found:
     /* Now know where the strtab and symtab are.  Snarf them. */
-    s = malloc(sizeof(*s));
-    syms = malloc(symtab.sh_size);
-    if (!syms) {
-        free(s);
-        return;
-    }
-    s->disas_strtab = strings = malloc(strtab.sh_size);
-    if (!s->disas_strtab) {
-        free(s);
-        free(syms);
-        return;
-    }
+    s = g_new(struct syminfo, 1);
+    syms = g_new(symtab.sh_size, 1);
+    s->disas_strtab = strings = g_new(strtab.sh_size, 1);
 
     lseek(fd, symtab.sh_offset, SEEK_SET);
     if (read(fd, syms, symtab.sh_size) != symtab.sh_size) {
-        free(s);
-        free(syms);
-        free(strings);
+        g_free(s);
+        g_free(syms);
+        g_free(strings);
         return;
     }
 
@@ -1113,22 +1099,16 @@  static void load_symbols(struct elfhdr *hdr, int fd)
         that we threw away.  Whether or not this has any effect on the
         memory allocation depends on the malloc implementation and how
         many symbols we managed to discard. */
-    new_syms = realloc(syms, nsyms * sizeof(*syms));
-    if (new_syms == NULL) {
-        free(s);
-        free(syms);
-        free(strings);
-        return;
-    }
+    new_syms = g_realloc(syms, nsyms * sizeof(*syms));
     syms = new_syms;
 
     qsort(syms, nsyms, sizeof(*syms), symcmp);
 
     lseek(fd, strtab.sh_offset, SEEK_SET);
     if (read(fd, strings, strtab.sh_size) != strtab.sh_size) {
-        free(s);
-        free(syms);
-        free(strings);
+        g_free(s);
+        g_free(syms);
+        g_free(strings);
         return;
     }
     s->disas_num_syms = nsyms;
@@ -1190,10 +1170,7 @@  int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     }
 
     /* Now read in all of the header information */
-    elf_phdata = (struct elf_phdr *)malloc(elf_ex.e_phentsize*elf_ex.e_phnum);
-    if (elf_phdata == NULL) {
-        return -ENOMEM;
-    }
+    elf_phdata = g_new(elf_ex.e_phentsize, elf_ex.e_phnum);
 
     retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET);
     if(retval > 0) {
@@ -1203,9 +1180,8 @@  int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 
     if (retval < 0) {
         perror("load_elf_binary");
+        g_free(elf_phdata);
         exit(-1);
-        free (elf_phdata);
-        return -errno;
     }
 
 #ifdef BSWAP_NEEDED
@@ -1231,8 +1207,8 @@  int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
         if (elf_ppnt->p_type == PT_INTERP) {
             if ( elf_interpreter != NULL )
             {
-                free (elf_phdata);
-                free(elf_interpreter);
+                g_free(elf_phdata);
+                g_free(elf_interpreter);
                 close(bprm->fd);
                 return -EINVAL;
             }
@@ -1242,13 +1218,7 @@  int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
              * is an a.out format binary
              */
 
-            elf_interpreter = (char *)malloc(elf_ppnt->p_filesz);
-
-            if (elf_interpreter == NULL) {
-                free (elf_phdata);
-                close(bprm->fd);
-                return -ENOMEM;
-            }
+            elf_interpreter = g_new(elf_ppnt->p_filesz, 1);
 
             retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET);
             if(retval >= 0) {
@@ -1297,11 +1267,10 @@  int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
             }
             if (retval < 0) {
                 perror("load_elf_binary3");
-                exit(-1);
-                free (elf_phdata);
-                free(elf_interpreter);
+                g_free(elf_phdata);
+                g_free(elf_interpreter);
                 close(bprm->fd);
-                return retval;
+                exit(-1);
             }
         }
         elf_ppnt++;
@@ -1323,8 +1292,8 @@  int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
         }
 
         if (!interpreter_type) {
-            free(elf_interpreter);
-            free(elf_phdata);
+            g_free(elf_interpreter);
+            g_free(elf_phdata);
             close(bprm->fd);
             return -ELIBBAD;
         }
@@ -1346,8 +1315,8 @@  int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
             }
         }
         if (!bprm->p) {
-            free(elf_interpreter);
-            free (elf_phdata);
+            g_free(elf_interpreter);
+            g_free(elf_phdata);
             close(bprm->fd);
             return -E2BIG;
         }
@@ -1486,17 +1455,16 @@  int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
         reloc_func_desc = interp_load_addr;
 
         close(interpreter_fd);
-        free(elf_interpreter);
+        g_free(elf_interpreter);
 
         if (elf_entry == ~((abi_ulong)0UL)) {
             printf("Unable to load interpreter\n");
-            free(elf_phdata);
+            g_free(elf_phdata);
             exit(-1);
-            return 0;
         }
     }
 
-    free(elf_phdata);
+    g_free(elf_phdata);
 
     if (qemu_log_enabled())
         load_symbols(&elf_ex, bprm->fd);