[PATCH 1/4] Sync canonicalize with gnulib [BZ #10635]

Adhemerval Zanella adhemerval.zanella@linaro.org
Tue Oct 27 12:59:20 GMT 2020


Ping.

On 10/09/2020 12:19, Adhemerval Zanella wrote:
> It sync with gnulib version 44358d4d165b with the following exceptions:
> 
>   - All the logic to which __getcwd use.
> 
>   - MAXSYMLINKS define (glibc already handles it on eloop-threshold.h).
> 
>   - The pathmax.h logic to handle //path (neither Linux nor Hurd makes
>     this distinction).
> 
>   - Don't explict set ENOMEM on malloc failure (it is already handled
>     by malloc itself).
> 
>   - The usage of malloca.h routines.
> 
> Checked on x86_64-linux-gnu
> ---
>  stdlib/canonicalize.c | 244 +++++++++++++++++++++++-------------------
>  1 file changed, 131 insertions(+), 113 deletions(-)
> 
> diff --git a/stdlib/canonicalize.c b/stdlib/canonicalize.c
> index cbd885a3c5..c58439b3fd 100644
> --- a/stdlib/canonicalize.c
> +++ b/stdlib/canonicalize.c
> @@ -16,8 +16,9 @@
>     License along with the GNU C Library; if not, see
>     <https://www.gnu.org/licenses/>.  */
>  
> -#include <assert.h>
>  #include <stdlib.h>
> +
> +#include <alloca.h>
>  #include <string.h>
>  #include <unistd.h>
>  #include <limits.h>
> @@ -29,10 +30,10 @@
>  #include <shlib-compat.h>
>  
>  /* Return the canonical absolute name of file NAME.  A canonical name
> -   does not contain any `.', `..' components nor any repeated path
> +   does not contain any ".", ".." components nor any repeated path
>     separators ('/') or symlinks.  All path components must exist.  If
>     RESOLVED is null, the result is malloc'd; otherwise, if the
> -   canonical name is PATH_MAX chars or more, returns null with `errno'
> +   canonical name is PATH_MAX chars or more, returns null with 'errno'
>     set to ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars,
>     returns the name in RESOLVED.  If the name cannot be resolved and
>     RESOLVED is non-NULL, it contains the path of the first component
> @@ -50,9 +51,9 @@ __realpath (const char *name, char *resolved)
>    if (name == NULL)
>      {
>        /* As per Single Unix Specification V2 we must return an error if
> -	 either parameter is a null pointer.  We extend this to allow
> -	 the RESOLVED parameter to be NULL in case the we are expected to
> -	 allocate the room for the return value.  */
> +         either parameter is a null pointer.  We extend this to allow
> +         the RESOLVED parameter to be NULL in case the we are expected to
> +         allocate the room for the return value.  */
>        __set_errno (EINVAL);
>        return NULL;
>      }
> @@ -60,7 +61,7 @@ __realpath (const char *name, char *resolved)
>    if (name[0] == '\0')
>      {
>        /* As per Single Unix Specification V2 we must return an error if
> -	 the name argument points to an empty string.  */
> +         the name argument points to an empty string.  */
>        __set_errno (ENOENT);
>        return NULL;
>      }
> @@ -70,152 +71,169 @@ __realpath (const char *name, char *resolved)
>  #else
>    path_max = __pathconf (name, _PC_PATH_MAX);
>    if (path_max <= 0)
> -    path_max = 1024;
> +    path_max = 8192;
>  #endif
>  
>    if (resolved == NULL)
>      {
>        rpath = malloc (path_max);
>        if (rpath == NULL)
> -	return NULL;
> +        return NULL;
>      }
>    else
>      rpath = resolved;
>    rpath_limit = rpath + path_max;
>  
> +
>    if (name[0] != '/')
>      {
>        if (!__getcwd (rpath, path_max))
> -	{
> -	  rpath[0] = '\0';
> -	  goto error;
> -	}
> -      dest = __rawmemchr (rpath, '\0');
> +        {
> +          rpath[0] = '\0';
> +          goto error;
> +        }
> +      dest = strchr (rpath, '\0');
>      }
>    else
>      {
> -      rpath[0] = '/';
> -      dest = rpath + 1;
> +      dest = rpath;
> +      *dest++ = '/';
>      }
> +  start = name;
>  
> -  for (start = end = name; *start; start = end)
> +  for (end = start; *start; start = end)
>      {
> +#ifdef _LIBC
>        struct stat64 st;
> -      int n;
> +#else
> +      struct stat st;
> +#endif
>  
>        /* Skip sequence of multiple path-separators.  */
>        while (*start == '/')
> -	++start;
> +        ++start;
>  
>        /* Find end of path component.  */
>        for (end = start; *end && *end != '/'; ++end)
> -	/* Nothing.  */;
> +        /* Nothing.  */;
>  
>        if (end - start == 0)
> -	break;
> +        break;
>        else if (end - start == 1 && start[0] == '.')
> -	/* nothing */;
> +        /* nothing */;
>        else if (end - start == 2 && start[0] == '.' && start[1] == '.')
> -	{
> -	  /* Back up to previous component, ignore if at root already.  */
> -	  if (dest > rpath + 1)
> -	    while ((--dest)[-1] != '/');
> -	}
> +        {
> +          /* Back up to previous component, ignore if at root already.  */
> +          if (dest > rpath + 1)
> +            for (--dest; dest > rpath && dest[-1] != '/'; --dest)
> +              continue;
> +        }
>        else
> -	{
> -	  size_t new_size;
> -
> -	  if (dest[-1] != '/')
> -	    *dest++ = '/';
> -
> -	  if (dest + (end - start) >= rpath_limit)
> -	    {
> -	      ptrdiff_t dest_offset = dest - rpath;
> -	      char *new_rpath;
> -
> -	      if (resolved)
> -		{
> -		  __set_errno (ENAMETOOLONG);
> -		  if (dest > rpath + 1)
> -		    dest--;
> -		  *dest = '\0';
> -		  goto error;
> -		}
> -	      new_size = rpath_limit - rpath;
> -	      if (end - start + 1 > path_max)
> -		new_size += end - start + 1;
> -	      else
> -		new_size += path_max;
> -	      new_rpath = (char *) realloc (rpath, new_size);
> -	      if (new_rpath == NULL)
> -		goto error;
> -	      rpath = new_rpath;
> -	      rpath_limit = rpath + new_size;
> -
> -	      dest = rpath + dest_offset;
> -	    }
> -
> -	  dest = __mempcpy (dest, start, end - start);
> -	  *dest = '\0';
> -
> -	  if (__lxstat64 (_STAT_VER, rpath, &st) < 0)
> -	    goto error;
> -
> -	  if (S_ISLNK (st.st_mode))
> -	    {
> -	      char *buf = __alloca (path_max);
> -	      size_t len;
> -
> -	      if (++num_links > __eloop_threshold ())
> -		{
> -		  __set_errno (ELOOP);
> -		  goto error;
> -		}
> -
> -	      n = __readlink (rpath, buf, path_max - 1);
> -	      if (n < 0)
> -		goto error;
> -	      buf[n] = '\0';
> -
> -	      if (!extra_buf)
> -		extra_buf = __alloca (path_max);
> -
> -	      len = strlen (end);
> -	      if (path_max - n <= len)
> -		{
> -		  __set_errno (ENAMETOOLONG);
> -		  goto error;
> -		}
> -
> -	      /* Careful here, end may be a pointer into extra_buf... */
> -	      memmove (&extra_buf[n], end, len + 1);
> -	      name = end = memcpy (extra_buf, buf, n);
> -
> -	      if (buf[0] == '/')
> -		dest = rpath + 1;	/* It's an absolute symlink */
> -	      else
> -		/* Back up to previous component, ignore if at root already: */
> -		if (dest > rpath + 1)
> -		  while ((--dest)[-1] != '/');
> -	    }
> -	  else if (!S_ISDIR (st.st_mode) && *end != '\0')
> -	    {
> -	      __set_errno (ENOTDIR);
> -	      goto error;
> -	    }
> -	}
> +        {
> +          size_t new_size;
> +
> +          if (dest[-1] != '/')
> +            *dest++ = '/';
> +
> +          if (dest + (end - start) >= rpath_limit)
> +            {
> +              ptrdiff_t dest_offset = dest - rpath;
> +              char *new_rpath;
> +
> +              if (resolved)
> +                {
> +                  __set_errno (ENAMETOOLONG);
> +                  if (dest > rpath + 1)
> +                    dest--;
> +                  *dest = '\0';
> +                  goto error;
> +                }
> +              new_size = rpath_limit - rpath;
> +              if (end - start + 1 > path_max)
> +                new_size += end - start + 1;
> +              else
> +                new_size += path_max;
> +              new_rpath = (char *) realloc (rpath, new_size);
> +              if (new_rpath == NULL)
> +                goto error;
> +              rpath = new_rpath;
> +              rpath_limit = rpath + new_size;
> +
> +              dest = rpath + dest_offset;
> +            }
> +
> +          dest = __mempcpy (dest, start, end - start);
> +          *dest = '\0';
> +
> +          if (__lxstat64 (_STAT_VER, rpath, &st) < 0)
> +            goto error;
> +
> +          if (S_ISLNK (st.st_mode))
> +            {
> +              char *buf = __alloca (path_max);
> +              size_t len;
> +              ssize_t n;
> +
> +              if (++num_links > __eloop_threshold ())
> +                {
> +                  __set_errno (ELOOP);
> +                  goto error;
> +                }
> +
> +              n = __readlink (rpath, buf, path_max - 1);
> +              if (n < 0)
> +                goto error;
> +              buf[n] = '\0';
> +
> +              if (!extra_buf)
> +                extra_buf = __alloca (path_max);
> +
> +              len = strlen (end);
> +              /* Check that n + len + 1 doesn't overflow and is <= path_max. */
> +              if (n >= SIZE_MAX - len || n + len >= path_max)
> +                {
> +                  __set_errno (ENAMETOOLONG);
> +                  goto error;
> +                }
> +
> +              /* Careful here, end may be a pointer into extra_buf... */
> +              memmove (&extra_buf[n], end, len + 1);
> +              name = end = memcpy (extra_buf, buf, n);
> +
> +              if (buf[0] == '/')
> +                {
> +                  dest = rpath;
> +                  *dest++ = '/'; /* It's an absolute symlink */
> +                }
> +              else
> +                {
> +                  /* Back up to previous component, ignore if at root
> +                     already: */
> +                  if (dest > rpath + 1)
> +                    for (--dest; dest > rpath && dest[-1] != '/'; --dest)
> +                      continue;
> +                }
> +            }
> +          else if (!S_ISDIR (st.st_mode) && *end != '\0')
> +            {
> +              __set_errno (ENOTDIR);
> +              goto error;
> +            }
> +        }
>      }
>    if (dest > rpath + 1 && dest[-1] == '/')
>      --dest;
>    *dest = '\0';
>  
> -  assert (resolved == NULL || resolved == rpath);
>    return rpath;
>  
>  error:
> -  assert (resolved == NULL || resolved == rpath);
> -  if (resolved == NULL)
> -    free (rpath);
> +  {
> +    int saved_errno = errno;
> +    if (resolved == NULL)
> +      free (rpath);
> +    __set_errno (saved_errno);
> +  }
>    return NULL;
>  }
>  libc_hidden_def (__realpath)
> 


More information about the Libc-alpha mailing list