Hi,

On Wed, Aug 26, 2015 at 12:29:13AM +0200, Steffan Karger wrote:
> As reported by Bill Parker in trac #600, strdup() return values are not
> always correctly checked for failed allocations.  This patch adds missing
> checks.
> 
> Note that in misc.c and options.c, the check is after the dirname() or
> basename() call, because these can deal with NULL params and we need to
> keep MSVC happy with its ancient no-declaration-after-statement policy.

Even though Arne has already ACKed it, I'm not merging it - I started
merging it today, but the more I stare at the code, the more I'm convinced
that we should just get rid of strdup() instead and/or the code is not
needed.

Why...?  Let me comment...

> diff --git a/src/openvpn/cryptoapi.c b/src/openvpn/cryptoapi.c
> index b7fc11e..62f30be 100644
> --- a/src/openvpn/cryptoapi.c
> +++ b/src/openvpn/cryptoapi.c
> @@ -127,6 +127,7 @@ static char *ms_error_text(DWORD ms_err)
>                   break;
>           }
>      }
> +    check_malloc_return(rv);
>      return rv;
>  }

This is not needed, as the code does

        rv = strdup(lpMsgBuf);
        LocalFree(lpMsgBuf);
        /* trim to the left */
        if (rv)
            for (p = rv + strlen(rv) - 1; p >= rv; p--) {
                if (isspace(*p))
                    *p = '\0';
                else
                    break;
            }
    }
    return rv;

... so if the strdup() fails, the function falls into "return NULL",
which is the same return value as for "if (!lpMsgBuf)", so I assume
the caller expects this - with the extra check, a failure in
FormatMessage() would be flagged as memory allocation failure (because
rv is set to NULL at start), which it isn't.

So, just not needed.

> diff --git a/src/openvpn/init.c b/src/openvpn/init.c
> index b7c153b..0809cc7 100644
> --- a/src/openvpn/init.c
> +++ b/src/openvpn/init.c
> @@ -817,6 +817,7 @@ init_options_dev (struct options *options)
>  {
>    if (!options->dev && options->dev_node) {
>      char *dev_node = strdup(options->dev_node); /* POSIX basename() 
> implementaions may modify its arguments */
> +    check_malloc_return(dev_node);
>      options->dev = basename (dev_node);
>    }
>  }

I'd need to look into this in more detail, but I think we never modify
options->dev_node afterward - so a simple strrchr() to find the "/" and
point options->dev there might be sufficient... but if it actually needs
to be a true copy, we should just use 

  char *dev_node = string_alloc(options->dev_node, NULL)

instead - string_alloc() is OpenVPN's strdup(), and "NULL" tells it
"do not use gc, use calloc" (side note: someone seriously overengineered
the "we really want clean memory!" bit here - allocating <n> bytes and
immediately overwriting with a n-byte memcpy() should be good enough,
no?) - *and* string_alloc() actually does...

      if (gc) {
...
      } else {
        ret = calloc(1, n);
        check_malloc_return(ret);
      }
      memcpy (ret, str, n);

... so the check_malloc_return() is built-in.


> diff --git a/src/openvpn/misc.c b/src/openvpn/misc.c
> index a5bad0d..b543b65 100644
> --- a/src/openvpn/misc.c
> +++ b/src/openvpn/misc.c
> @@ -1608,6 +1608,7 @@ argv_extract_cmd_name (const char *path)
>      {
>        char *path_cp = strdup(path); /* POSIX basename() implementaions may 
> modify its arguments */
>        const char *bn = basename (path_cp);
> +      check_malloc_return(path_cp);
>        if (bn)
>       {
>         char *ret = string_alloc (bn, NULL);

This is totally weird code, using strdup() first, and then string_alloc()
later, inside an "if (bn)" check on a variable that will never be NULL
anyway, since basename(NULL) is documented to return "." - and it very
much looks like two different persons wrote this part :-)

Dunno, this really smells like refactor the function to use strrchr()
on the original path, and then use string_alloc($ptr, NULL) to make
a copy of that... throw out the if(bn) block, and be done...  or just
change the strdup() to string_alloc() as well.


> diff --git a/src/openvpn/options.c b/src/openvpn/options.c
> index 2784580..dba7c9d 100644
> --- a/src/openvpn/options.c
> +++ b/src/openvpn/options.c
> @@ -2588,6 +2588,7 @@ check_file_access(const int type, const char *file, 
> const int mode, const char *
>      {
>        char *fullpath = strdup(file);  /* POSIX dirname() implementaion may 
> modify its arguments */
>        char *dirpath = dirname(fullpath);
> +      check_malloc_return(fullpath);
>  
>        if (platform_access (dirpath, mode|X_OK) != 0)
>            errcode = errno;

string_alloc()  (pity we do not have a gc around here :-) )

> diff --git a/src/openvpn/ssl_polarssl.c b/src/openvpn/ssl_polarssl.c
> index 3fc811e..673dbbe 100644
> --- a/src/openvpn/ssl_polarssl.c
> +++ b/src/openvpn/ssl_polarssl.c
> @@ -198,6 +198,7 @@ tls_ctx_restrict_ciphers(struct tls_root_ctx *ctx, const 
> char *ciphers)
>    /* Parse allowed ciphers, getting IDs */
>    i = 0;
>    tmp_ciphers_orig = tmp_ciphers = strdup(ciphers);
> +  check_malloc_return(tmp_ciphers);
>  
>    token = strtok (tmp_ciphers, ":");
>    while(token)

I could mention string_alloc() again, but I'm sure interested readers
already recognize the pattern :-))

gert

-- 
USENET is *not* the non-clickable part of WWW!
                                                           //www.muc.de/~gert/
Gert Doering - Munich, Germany                             g...@greenie.muc.de
fax: +49-89-35655025                        g...@net.informatik.tu-muenchen.de

Attachment: pgp4ftFfP_EmE.pgp
Description: PGP signature

Reply via email to