Bug Summary

File:lib/realpathat.c
Warning:line 82, column 18
Although the value stored to 'end' is used in the enclosing expression, the value is never actually read from 'end'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name realpathat.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -fno-plt -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/home/buildbot/lwan-worker/clang-analyze/build/src/lib -resource-dir /usr/lib/clang/13.0.0 -include /home/buildbot/lwan-worker/clang-analyze/build/lwan-build-config.h -D _FILE_OFFSET_BITS=64 -D _TIME_BITS=64 -I /home/buildbot/lwan-worker/clang-analyze/build/src/lib/missing -I /usr/include/luajit-2.0 -I /usr/include/valgrind -I /home/buildbot/lwan-worker/clang-analyze/build/src/lib -I /home/buildbot/lwan-worker/clang-analyze/build -internal-isystem /usr/lib/clang/13.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/11.1.0/../../../../x86_64-pc-linux-gnu/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-unused-parameter -Wno-free-nonheap-object -std=gnu99 -fdebug-compilation-dir=/home/buildbot/lwan-worker/clang-analyze/build/src/lib -ferror-limit 19 -stack-protector 2 -fgnuc-version=4.2.1 -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/buildbot/lwan-worker/clang-analyze/CLANG/2021-11-25-183857-338264-1 -x c /home/buildbot/lwan-worker/clang-analyze/build/src/lib/realpathat.c
1/* -at() version of realpath()
2 Copyright (C) 2012 L. A. F. Pereira
3
4 Based on: return the canonical absolute name of a given file.
5 Copyright (C) 1996-2002,2004,2005,2006,2008 Free Software Foundation, Inc.
6 This file is part of the GNU C Library.
7
8 The GNU C Library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2.1 of the License, or (at your option) any later version.
12
13 The GNU C Library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public
19 License along with the GNU C Library; if not, see
20 <http://www.gnu.org/licenses/>. */
21
22#define _GNU_SOURCE
23#include <assert.h>
24#include <errno(*__errno_location ()).h>
25#include <fcntl.h>
26#include <limits.h>
27#include <stddef.h>
28#include <stdlib.h>
29#include <string.h>
30#include <string.h>
31#include <sys/param.h>
32#include <sys/stat.h>
33#include <unistd.h>
34
35#include "lwan-private.h"
36
37char *
38realpathat2(int dirfd, char *dirfdpath, const char *name, char *resolved,
39 struct stat *st)
40{
41 char *rpath, *dest, extra_buf[PATH_MAX4096];
42 const char *start, *end, *rpath_limit;
43 int num_links = 0;
44 ptrdiff_t dirfdlen;
45 char *pathat;
46
47 if (UNLIKELY(name == NULL)__builtin_expect(((name == ((void*)0))), (0))) {
48 /* As per Single Unix Specification V2 we must return an error if
49 either parameter is a null pointer. We extend this to allow
50 the RESOLVED parameter to be NULL in case the we are expected to
51 allocate the room for the return value. */
52 errno(*__errno_location ()) = EINVAL22;
53 return NULL((void*)0);
54 }
55
56 /* If any of the additional parameters are null, or if the name to
57 resolve the real path is an absolute path, use the standard
58 realpath() routine. */
59 if (UNLIKELY(dirfd < 0 || dirfdpath == NULL || name[0] == '/')__builtin_expect(((dirfd < 0 || dirfdpath == ((void*)0) ||
name[0] == '/')), (0))
)
60 return realpath(name, resolved);
61
62 if (name[0] == '\0') {
63 if (UNLIKELY(fstat(dirfd, st) < 0)__builtin_expect(((fstat(dirfd, st) < 0)), (0)))
64 return NULL((void*)0);
65 if (LIKELY(!resolved)__builtin_expect((!!(!resolved)), (1)))
66 return strdup(dirfdpath);
67 return strcpy(resolved, dirfdpath);
68 }
69
70 if (LIKELY(!resolved)__builtin_expect((!!(!resolved)), (1))) {
71 rpath = malloc(PATH_MAX4096);
72 if (UNLIKELY(!rpath)__builtin_expect(((!rpath)), (0)))
73 return NULL((void*)0);
74 } else
75 rpath = resolved;
76 rpath_limit = rpath + PATH_MAX4096;
77
78 strcpy(rpath, dirfdpath);
79 dest = rpath + strlen(rpath);
80 dirfdlen = dest - rpath;
81
82 for (start = end = name; *start; start = end) {
Although the value stored to 'end' is used in the enclosing expression, the value is never actually read from 'end'
83 int n;
84
85 /* Skip sequence of multiple path-separators. */
86 while (*start == '/')
87 ++start;
88
89 /* Find end of path component. */
90 for (end = start; *end && *end != '/'; ++end)
91 /* Nothing. */ ;
92
93 if (end - start == 0)
94 break;
95 else if (end - start == 1 && start[0] == '.')
96 /* nothing */ ;
97 else if (end - start == 2 && start[0] == '.' && start[1] == '.') {
98 /* Back up to previous component, ignore if at root already. */
99 if (dest > rpath + 1)
100 while ((--dest)[-1] != '/');
101 } else {
102 size_t new_size;
103
104 if (dest[-1] != '/')
105 *dest++ = '/';
106
107 if (dest + (end - start) >= rpath_limit) {
108 ptrdiff_t dest_offset = dest - rpath;
109 char *new_rpath;
110
111 if (UNLIKELY(resolved != NULL)__builtin_expect(((resolved != ((void*)0))), (0))) {
112 errno(*__errno_location ()) = ENAMETOOLONG36;
113 if (dest > rpath + 1)
114 dest--;
115 *dest = '\0';
116 goto error;
117 }
118
119 new_size = (size_t)(rpath_limit - rpath);
120 if (end - start + 1 > PATH_MAX4096)
121 new_size += (size_t)(end - start + 1);
122 else
123 new_size += PATH_MAX4096;
124 new_rpath = (char *) realloc(rpath, new_size);
125 if (UNLIKELY(new_rpath == NULL)__builtin_expect(((new_rpath == ((void*)0))), (0)))
126 goto error;
127 rpath = new_rpath;
128 rpath_limit = rpath + new_size;
129
130 dest = rpath + dest_offset;
131 }
132
133 dest = mempmove(dest, start, (size_t)(end - start));
134 *dest = '\0';
135
136 if ((dirfdlen == 1 && *dirfdpath == '/') ||
137 strncmp(rpath, dirfdpath, (size_t)dirfdlen)) {
138 pathat = rpath;
139 } else {
140 pathat = rpath + dirfdlen;
141 }
142 if (UNLIKELY(*pathat == '\0')__builtin_expect(((*pathat == '\0')), (0)))
143 pathat = rpath;
144
145 if (UNLIKELY(fstatat(dirfd, pathat, st, AT_SYMLINK_NOFOLLOW) < 0)__builtin_expect(((fstatat(dirfd, pathat, st, 0x100) < 0))
, (0))
)
146 goto error;
147
148 if (UNLIKELY(S_ISLNK(st->st_mode))__builtin_expect(((((((st->st_mode)) & 0170000) == (0120000
)))), (0))
) {
149 char buf[PATH_MAX4096];
150 size_t len;
151
152 if (UNLIKELY(++num_links > MAXSYMLINKS)__builtin_expect(((++num_links > 20)), (0))) {
153 errno(*__errno_location ()) = ELOOP40;
154 goto error;
155 }
156
157 n = (int)readlinkat(dirfd, pathat, buf, PATH_MAX4096 - 1);
158 if (UNLIKELY(n < 0)__builtin_expect(((n < 0)), (0)))
159 goto error;
160 buf[n] = '\0';
161
162 len = strlen(end);
163 if (UNLIKELY((size_t)(PATH_MAX - n) <= len)__builtin_expect((((size_t)(4096 - n) <= len)), (0))) {
164 errno(*__errno_location ()) = ENAMETOOLONG36;
165 goto error;
166 }
167
168 /* Careful here, end may be a pointer into extra_buf... */
169 memmove(&extra_buf[n], end, len + 1);
170 end = memcpy(extra_buf, buf, (size_t)n);
171
172 if (buf[0] == '/')
173 dest = rpath + 1; /* It's an absolute symlink */
174 else
175 /* Back up to previous component, ignore if at root already: */
176 if (dest > rpath + 1)
177 while ((--dest)[-1] != '/');
178 } else if (UNLIKELY(!S_ISDIR(st->st_mode) && *end != '\0')__builtin_expect(((!((((st->st_mode)) & 0170000) == (0040000
)) && *end != '\0')), (0))
) {
179 errno(*__errno_location ()) = ENOTDIR20;
180 goto error;
181 }
182 }
183 }
184
185 if (dest > rpath + 1 && dest[-1] == '/')
186 --dest;
187 *dest = '\0';
188
189 assert(resolved == NULL || resolved == rpath)((void) sizeof ((resolved == ((void*)0) || resolved == rpath)
? 1 : 0), __extension__ ({ if (resolved == ((void*)0) || resolved
== rpath) ; else __assert_fail ("resolved == NULL || resolved == rpath"
, "/home/buildbot/lwan-worker/clang-analyze/build/src/lib/realpathat.c"
, 189, __extension__ __PRETTY_FUNCTION__); }))
;
190 return rpath;
191
192 error:
193 assert(resolved == NULL || resolved == rpath)((void) sizeof ((resolved == ((void*)0) || resolved == rpath)
? 1 : 0), __extension__ ({ if (resolved == ((void*)0) || resolved
== rpath) ; else __assert_fail ("resolved == NULL || resolved == rpath"
, "/home/buildbot/lwan-worker/clang-analyze/build/src/lib/realpathat.c"
, 193, __extension__ __PRETTY_FUNCTION__); }))
;
194 if (resolved == NULL((void*)0))
195 free(rpath);
196 return NULL((void*)0);
197}
198
199char *
200realpathat(int dirfd, char *dirfdpath, const char *name, char *resolved)
201{
202 struct stat st;
203 return realpathat2(dirfd, dirfdpath, name, resolved, &st);
204}