diff mbox

[PATCHv3,2/2] envlist.c: handle strdup failure

Message ID 1337681798-22395-3-git-send-email-jim@meyering.net
State New
Headers show

Commit Message

Jim Meyering May 22, 2012, 10:16 a.m. UTC
From: Jim Meyering <meyering@redhat.com>

Without this, envlist_to_environ may silently fail to copy all
strings into the destination buffer, and both callers would leak
any env strings allocated after a failing strdup, because the
freeing code stops at the first NULL pointer.

Signed-off-by: Jim Meyering <meyering@redhat.com>
---
 envlist.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

Comments

Andreas Färber Aug. 17, 2012, 4:03 p.m. UTC | #1
Am 22.05.2012 12:16, schrieb Jim Meyering:
> From: Jim Meyering <meyering@redhat.com>
> 
> Without this, envlist_to_environ may silently fail to copy all
> strings into the destination buffer, and both callers would leak
> any env strings allocated after a failing strdup, because the
> freeing code stops at the first NULL pointer.
> 
> Signed-off-by: Jim Meyering <meyering@redhat.com>
> ---
>  envlist.c | 12 ++++++++++--
>  1 file changed, 10 insertions(+), 2 deletions(-)
> 
> diff --git a/envlist.c b/envlist.c
> index e44889b..df5c723 100644
> --- a/envlist.c
> +++ b/envlist.c
> @@ -234,8 +234,16 @@ envlist_to_environ(const envlist_t *envlist, size_t *count)
>          return (NULL);
> 
>      for (entry = envlist->el_entries.lh_first; entry != NULL;
> -        entry = entry->ev_link.le_next) {
> -        *(penv++) = strdup(entry->ev_var);
> +         entry = entry->ev_link.le_next, penv++) {

Scratch my comment on 1/2, there's an added penv++ that I overlooked.
Not changing the indentation twice would still be nice.

> +        *penv = strdup(entry->ev_var);
> +        if (*penv == NULL) {
> +            char **e = env;
> +            while (e <= penv) {
> +                free(*e++);
> +            }
> +            free(env);
> +            return NULL;
> +        }
>      }
>      *penv = NULL; /* NULL terminate the list */
> 

This leak fix looks good then.

For anyone wondering like me, the "env" here is not the usual
CPUArchState *env but a local char **env.

Andreas
Jim Meyering Aug. 17, 2012, 6:30 p.m. UTC | #2
Andreas Färber wrote:
> Am 22.05.2012 12:16, schrieb Jim Meyering:
>> From: Jim Meyering <meyering@redhat.com>
>>
>> Without this, envlist_to_environ may silently fail to copy all
>> strings into the destination buffer, and both callers would leak
>> any env strings allocated after a failing strdup, because the
>> freeing code stops at the first NULL pointer.
>>
>> Signed-off-by: Jim Meyering <meyering@redhat.com>
>> ---
>>  envlist.c | 12 ++++++++++--
>>  1 file changed, 10 insertions(+), 2 deletions(-)
>>
>> diff --git a/envlist.c b/envlist.c
>> index e44889b..df5c723 100644
>> --- a/envlist.c
>> +++ b/envlist.c
>> @@ -234,8 +234,16 @@ envlist_to_environ(const envlist_t *envlist, size_t *count)
>>          return (NULL);
>>
>>      for (entry = envlist->el_entries.lh_first; entry != NULL;
>> -        entry = entry->ev_link.le_next) {
>> -        *(penv++) = strdup(entry->ev_var);
>> +         entry = entry->ev_link.le_next, penv++) {
>
> Scratch my comment on 1/2, there's an added penv++ that I overlooked.
> Not changing the indentation twice would still be nice.

I posted a V4 that does that, and removes parens around return arguments
as well.  However, I did not remove assignments from conditionals.  IMHO,
that would require an inordinate amount of change for the marginal gain
of making legacy code conform.
diff mbox

Patch

diff --git a/envlist.c b/envlist.c
index e44889b..df5c723 100644
--- a/envlist.c
+++ b/envlist.c
@@ -234,8 +234,16 @@  envlist_to_environ(const envlist_t *envlist, size_t *count)
         return (NULL);

     for (entry = envlist->el_entries.lh_first; entry != NULL;
-        entry = entry->ev_link.le_next) {
-        *(penv++) = strdup(entry->ev_var);
+         entry = entry->ev_link.le_next, penv++) {
+        *penv = strdup(entry->ev_var);
+        if (*penv == NULL) {
+            char **e = env;
+            while (e <= penv) {
+                free(*e++);
+            }
+            free(env);
+            return NULL;
+        }
     }
     *penv = NULL; /* NULL terminate the list */