Bug Summary

File:root/firefox-clang/config/pathsub.c
Warning:line 94, column 9
Access to field 'd_ino' results in a dereference of a null pointer (loaded from variable 'ep')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O3 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name pathsub.c -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 -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/config -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/config -resource-dir /usr/lib/llvm-23/lib/clang/23 -D XP_UNIX -D DEBUG=1 -D UNICODE -D _UNICODE -I /root/firefox-clang/config -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/config -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/15/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-07-16-093543-1626485-1 -x c /root/firefox-clang/config/pathsub.c
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4/*
5** Pathname subroutines.
6**
7** Brendan Eich, 8/29/95
8*/
9#include <assert.h>
10#include <sys/types.h>
11#include <dirent.h>
12#include <errno(*__errno_location ()).h>
13#include <stdarg.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <string.h>
17#include <unistd.h>
18#include <sys/stat.h>
19#include "pathsub.h"
20
21#ifdef USE_REENTRANT_LIBC
22# include <libc_r.h>
23#endif
24
25#ifdef SUNOS4
26# include "sunos4.h"
27#endif
28
29char* program;
30
31void fail(const char* format, ...) {
32 int error;
33 va_list ap;
34
35#ifdef USE_REENTRANT_LIBC
36 R_STRERROR_INIT_R();
37#endif
38
39 error = errno(*__errno_location ());
40 fprintf(stderrstderr, "%s: ", program);
41 va_start(ap, format)__builtin_va_start(ap, format);
42 vfprintf(stderrstderr, format, ap);
43 va_end(ap)__builtin_va_end(ap);
44 if (error) {
45#ifdef USE_REENTRANT_LIBC
46 R_STRERROR_R(errno(*__errno_location ()));
47 fprintf(stderrstderr, ": %s", r_strerror_r);
48#else
49 fprintf(stderrstderr, ": %s", strerror(errno(*__errno_location ())));
50#endif
51 }
52
53 putc('\n', stderrstderr);
54 exit(1);
55}
56
57char* getcomponent(char* path, char* name) {
58 if (*path == '\0') return 0;
59 if (*path == '/') {
60 *name++ = '/';
61 } else {
62 do {
63 *name++ = *path++;
64 } while (*path != '/' && *path != '\0');
65 }
66 *name = '\0';
67 while (*path == '/') path++;
68 return path;
69}
70
71#ifdef LAME_READDIR
72# include <sys/param.h>
73/*
74** The static buffer in Unixware's readdir is too small.
75*/
76struct dirent* readdir(DIR* d) {
77 static struct dirent* buf = NULL((void*)0);
78
79 if (buf == NULL((void*)0))
80 buf = (struct dirent*)malloc(sizeof(struct dirent) + MAXPATHLEN);
81 return (readdir_r(d, buf));
82}
83#endif
84
85char* ino2name(ino_t ino) {
86 DIR* dp;
87 struct dirent* ep;
88 char* name;
89
90 dp = opendir("..");
91 if (!dp
7.1
'dp' is non-null
) fail("cannot read parent directory");
8
Taking false branch
92 for (;;) {
9
Loop condition is true. Entering loop body
93 if (!(ep = readdir(dp))) fail("cannot find current directory");
10
Value assigned to 'ep'
11
Assuming 'ep' is null
12
Assuming pointer value is null
13
Taking true branch
94 if (ep->d_ino == ino) break;
14
Access to field 'd_ino' results in a dereference of a null pointer (loaded from variable 'ep')
95 }
96 name = xstrdup(ep->d_name);
97 closedir(dp);
98 return name;
99}
100
101void* xmalloc(size_t size) {
102 void* p = malloc(size);
103 if (!p) fail("cannot allocate %u bytes", size);
104 return p;
105}
106
107char* xstrdup(char* s) { return strcpy(xmalloc(strlen(s) + 1), s); }
108
109char* xbasename(char* path) {
110 char* cp;
111
112 while ((cp = strrchr(path, '/')) && cp[1] == '\0') *cp = '\0';
113 if (!cp) return path;
114 return cp + 1;
115}
116
117void xchdir(const char* dir) {
118 if (chdir(dir) < 0) fail("cannot change directory to %s", dir);
119}
120
121int relatepaths(char* from, char* to, char* outpath) {
122 char *cp, *cp2;
123 int len;
124 char buf[NAME_MAX256];
125
126 assert(*from == '/' && *to == '/')((void) sizeof ((*from == '/' && *to == '/') ? 1 : 0)
, __extension__ ({ if (*from == '/' && *to == '/') ; else
__assert_fail ("*from == '/' && *to == '/'", "/root/firefox-clang/config/pathsub.c"
, 126, __extension__ __PRETTY_FUNCTION__); }))
;
127 for (cp = to, cp2 = from; *cp == *cp2; cp++, cp2++)
128 if (*cp == '\0') break;
129 while (cp[-1] != '/') cp--, cp2--;
130 if (cp - 1 == to) {
131 /* closest common ancestor is /, so use full pathname */
132 len = strlen(strcpy(outpath, to));
133 if (outpath[len] != '/') {
134 outpath[len++] = '/';
135 outpath[len] = '\0';
136 }
137 } else {
138 len = 0;
139 while ((cp2 = getcomponent(cp2, buf)) != 0) {
140 strcpy(outpath + len, "../");
141 len += 3;
142 }
143 while ((cp = getcomponent(cp, buf)) != 0) {
144 sprintf(outpath + len, "%s/", buf);
145 len += strlen(outpath + len);
146 }
147 }
148 return len;
149}
150
151void reversepath(char* inpath, char* name, int len, char* outpath) {
152 char *cp, *cp2;
153 char buf[NAME_MAX256];
154 struct stat sb;
155
156 cp = strcpy(outpath + PATH_MAX4096 - (len + 1), name);
157 cp2 = inpath;
158 while ((cp2 = getcomponent(cp2, buf)) != 0) {
1
Loop condition is true. Entering loop body
159 if (strcmp(buf, ".") == 0) continue;
2
Assuming the condition is false
3
Taking false branch
160 if (strcmp(buf, "..") == 0) {
4
Assuming the condition is true
5
Taking true branch
161 if (stat(".", &sb) < 0) fail("cannot stat current directory");
6
Taking false branch
162 name = ino2name(sb.st_ino);
7
Calling 'ino2name'
163 len = strlen(name);
164 cp -= len + 1;
165 strcpy(cp, name);
166 cp[len] = '/';
167 free(name);
168 xchdir("..");
169 } else {
170 cp -= 3;
171 strncpy(cp, "../", 3);
172 xchdir(buf);
173 }
174 }
175 strcpy(outpath, cp);
176}