From patchwork Tue Oct 27 14:35:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella X-Patchwork-Id: 40886 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 44AC03953827; Tue, 27 Oct 2020 14:35:41 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 44AC03953827 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1603809341; bh=BTA5M2tyt0pBcHKrnG/m8ZAG8fcziW10FqFgv52Oco8=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=M4F/vohPcuqTEsZfzNGPKuMcvysQvxJf5OJrMflyxNKRYJWwbdq9TOS1RktuniIQQ e1ptkB3vJVM1qKgUBOpHH1rChmCWXPjuKfpLhQqKgDE4jeQIT3HGjTUTCvZ6B4zGAc QEuM5ha7yX+u/380U45HzcROGjeBz+ntmIoo3lsU= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-qk1-x72d.google.com (mail-qk1-x72d.google.com [IPv6:2607:f8b0:4864:20::72d]) by sourceware.org (Postfix) with ESMTPS id 104923851C34 for ; Tue, 27 Oct 2020 14:35:38 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 104923851C34 Received: by mail-qk1-x72d.google.com with SMTP id 140so1332855qko.2 for ; Tue, 27 Oct 2020 07:35:38 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=BTA5M2tyt0pBcHKrnG/m8ZAG8fcziW10FqFgv52Oco8=; b=G4bZDbtQJ0glgz/B92lZF4DdrFn/ouDyCM9mhcyutImJWyJGprFN23jB0llDTnRc/z wUrM4Jm7Q+f19jElvvwb3c21WhuvH6vdEICE3dT5XKaZZV+MjIgouGjiCf1MNcdpL2Zj m5qNaANh0Wo5G/4Fd9rBLHWA9GdAig6g5LNxwDcZDMLyml8JVQMql+m4Z0d0m1wyOrFe sZdg7iY/MBHeJ+UTzfBjXVg00HazrdTbfyAqsJjcMWr4tKiQiYfUSfndmRPBg0hQrtrP oeMMpW3e8BCyyW7M8nWjrVghkvELlRQmTZ21SBvoqPYgDjk8LalsmeA5+2bar9eQx/uJ gWuQ== X-Gm-Message-State: AOAM5311KVT3sCngPloU4aOtULlYZny3sWCin8czsX8ir5pMb8JPGp7G YaDHktY8VV/0X9xxh9Po5ojPKvFgCgajfQ== X-Google-Smtp-Source: ABdhPJyIa0OkmyGGHzKC/XtFvr85FnEHJmfS+XzgYNwaSMLHbXmAW8MmYzVuE0ZgojOePhOpCbzYmw== X-Received: by 2002:a05:620a:10b7:: with SMTP id h23mr2309961qkk.132.1603809336573; Tue, 27 Oct 2020 07:35:36 -0700 (PDT) Received: from localhost.localdomain ([177.194.48.209]) by smtp.googlemail.com with ESMTPSA id 19sm780704qki.33.2020.10.27.07.35.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 27 Oct 2020 07:35:36 -0700 (PDT) To: libc-alpha@sourceware.org Subject: [PATCH v2 1/4] Sync canonicalize with gnulib [BZ #10635] Date: Tue, 27 Oct 2020 11:35:28 -0300 Message-Id: <20201027143531.2448132-1-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 X-Spam-Status: No, score=-14.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Adhemerval Zanella via Libc-alpha From: Adhemerval Zanella Reply-To: Adhemerval Zanella Cc: Andreas Schwab Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" 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 3fcb399a5d..2770f4ae44 100644 --- a/stdlib/canonicalize.c +++ b/stdlib/canonicalize.c @@ -16,8 +16,9 @@ License along with the GNU C Library; if not, see . */ -#include #include + +#include #include #include #include @@ -29,10 +30,10 @@ #include /* 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 (__lstat64 (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 (__lstat64 (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)