Bug Summary

File:_build/../src/missing.cc
Warning:line 163, column 20
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name missing.cc -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -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 -mframe-pointer=none -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/_build -resource-dir /usr/lib/llvm-16/lib/clang/16 -I src/libbte-2.91.so.0.6500.0.p -I src -I ../src -I . -I .. -I src/bte -I ../src/bte -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/p11-kit-1 -I /usr/include/ctk-3.0 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/gio-unix-2.0 -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -D _GLIBCXX_ASSERTIONS=1 -D _FILE_OFFSET_BITS=64 -D G_LOG_DOMAIN="BTE" -D LOCALEDIR="/usr/local/share/locale" -D BTE_DISABLE_DEPRECATION_WARNINGS -D BTE_COMPILATION -U PARSER_INCLUDE_NOP -D CDK_VERSION_MIN_REQUIRED=(G_ENCODE_VERSION(3,18)) -D CDK_VERSION_MAX_ALLOWED=(G_ENCODE_VERSION(3,20)) -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/x86_64-linux-gnu/c++/13 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/backward -internal-isystem /usr/lib/llvm-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-address-of-packed-member -Wno-missing-field-initializers -Wno-packed -Wno-switch-enum -Wno-unused-parameter -Wwrite-strings -std=gnu++17 -fdeprecated-macro -fdebug-compilation-dir=/rootdir/_build -ferror-limit 19 -fvisibility=hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-08-05-222352-10670-1 -x c++ ../src/missing.cc
1/*
2 * Copyright © 2020 Christian Persch
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 3 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18#include "config.h"
19
20#ifdef HAVE_SYS_RESOURCE_H
21#include <sys/resource.h>
22#endif
23
24#include <glib-unix1.h>
25#include <gio/gio.h>
26
27#ifdef __linux__1
28#include <sys/syscall.h> /* for syscall and SYS_getdents64 */
29#endif
30
31#include "missing.hh"
32
33/* BEGIN copied from glib
34 *
35 * Code for fdwalk copied from glib/glib/gspawn.c, there under LGPL2.1+,
36 * and used here under LGPL3+.
37 *
38 * Copyright 2000 Red Hat, Inc.
39 */
40
41#ifndef HAVE_FDWALK
42
43#ifdef __linux__1
44
45struct linux_dirent64
46{
47 guint64 d_ino; /* 64-bit inode number */
48 guint64 d_off; /* 64-bit offset to next structure */
49 unsigned short d_reclen; /* Size of this dirent */
50 char d_name[]; /* Filename (null-terminated) */
51};
52
53/* This function is called between fork and execve/_exit and so must be
54 * async-signal-safe; see man:signal-safety(7).
55 */
56static int
57filename_to_fd (const char *p)
58{
59 char c;
60 int fd = 0;
61 const int cutoff = G_MAXINT2147483647 / 10;
62 const int cutlim = G_MAXINT2147483647 % 10;
63
64 if (*p == '\0')
65 return -1;
66
67 while ((c = *p++) != '\0')
68 {
69 if (c < '0' || c > '9')
70 return -1;
71 c -= '0';
72
73 /* Check for overflow. */
74 if (fd > cutoff || (fd == cutoff && c > cutlim))
75 return -1;
76
77 fd = fd * 10 + c;
78 }
79
80 return fd;
81}
82
83#endif /* __linux__ */
84
85/* This function is called between fork and execve/_exit and so must be
86 * async-signal-safe; see man:signal-safety(7).
87 */
88static rlim_t
89getrlimit_NOFILE_max(void)
90{
91#ifdef HAVE_SYS_RESOURCE_H
92#ifdef __linux__1
93{
94 struct rlimit rlim;
95
96 if (prlimit(0 /* this PID */, RLIMIT_NOFILERLIMIT_NOFILE, nullptr, &rlim) == 0)
97 return rlim.rlim_max;
98
99 return RLIM_INFINITY0xffffffffffffffffuLL;
100}
101#endif /* __linux__ */
102
103#ifdef __GLIBC__2
104{
105 struct rlimit rlim;
106
107 /* Use getrlimit() function provided by the system if it is known to be
108 * async-signal safe.
109 *
110 * According to the glibc manual, getrlimit is AS-safe.
111 */
112 if (getrlimit(RLIMIT_NOFILERLIMIT_NOFILE, &rlim) == 0)
113 return rlim.rlim_max;
114}
115
116 /* fallback */
117#endif /* __GLIBC__ */
118
119#endif /* HAVE_SYS_RESOURCE_H */
120
121#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
122 /* Use sysconf() function provided by the system if it is known to be
123 * async-signal safe.
124 */
125 auto const r = sysconf(_SC_OPEN_MAX_SC_OPEN_MAX);
126 if (r != -1)
127 return r;
128
129 /* fallback */
130#endif
131
132 /* couldn't determine, so potentially infinite */
133 return RLIM_INFINITY0xffffffffffffffffuLL;
134}
135
136/* This function is called between fork and execve/_exit and so must be
137 * async-signal-safe; see man:signal-safety(7).
138 */
139int
140fdwalk(int (*cb)(void *data, int fd),
141 void *data)
142{
143 /* Fallback implementation of fdwalk. It should be async-signal safe, but it
144 * may be slow on non-Linux operating systems, especially on systems allowing
145 * very high number of open file descriptors.
146 */
147 int fd;
148 int res = 0;
149
150#ifdef __linux__1
151 /* Avoid use of opendir/closedir since these are not async-signal-safe. */
152 int dir_fd = open ("/proc/self/fd", O_RDONLY00 | O_DIRECTORY0200000 | O_CLOEXEC02000000);
153 if (dir_fd >= 0)
154 {
155 char buf[4096];
156 int pos, nread;
157 struct linux_dirent64 *de;
158
159 while ((nread = syscall (SYS_getdents64217, dir_fd, buf, sizeof(buf))) > 0)
160 {
161 for (pos = 0; pos < nread; pos += de->d_reclen)
162 {
163 de = (struct linux_dirent64 *)(buf + pos);
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
164
165 fd = filename_to_fd (de->d_name);
166 if (fd < 0 || fd == dir_fd)
167 continue;
168
169 if ((res = cb (data, fd)) != 0)
170 break;
171 }
172 }
173
174 close (dir_fd);
175 return res;
176 }
177
178 /* If /proc is not mounted or not accessible we fall back to the old
179 * rlimit trick */
180
181#endif
182
183 auto const open_max = getrlimit_NOFILE_max();
184 if (open_max == RLIM_INFINITY0xffffffffffffffffuLL || open_max > G_MAXINT2147483647) {
185 /* We cannot close infinitely many FDs, but we also must not
186 * leak any FDs. Return an error.
187 */
188 errno(*__errno_location ()) = ENFILE23;
189 return -1;
190 }
191
192 for (fd = 0; fd < int(open_max); fd++)
193 if ((res = cb (data, fd)) != 0)
194 break;
195
196 return res;
197}
198#endif /* !HAVE_FDWALK */
199
200#ifndef HAVE_STRCHRNUL
201/* Copied from glib */
202char*
203strchrnul(char const* s,
204 int c)
205{
206 char *p = (char *) s;
207 while (*p && (*p != c))
208 ++p;
209
210 return p;
211}
212#endif /* !HAVE_STRCHRNUL */
213
214/* END copied from glib */