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().
> 
>
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);
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);