Bug Summary

File:src/bin/ls/print.c
Warning:line 193, column 17
Array access (from variable 'array') results in a null pointer dereference

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name print.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 -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/bin/ls/obj -resource-dir /usr/local/llvm16/lib/clang/16 -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/bin/ls/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/bin/ls/print.c
1/* $OpenBSD: print.c,v 1.40 2023/10/07 11:51:08 schwarze Exp $ */
2/* $NetBSD: print.c,v 1.15 1996/12/11 03:25:39 thorpej Exp $ */
3
4/*
5 * Copyright (c) 1989, 1993, 1994
6 * The Regents of the University of California. All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * Michael Fischbein.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#include <sys/types.h>
37#include <sys/stat.h>
38
39#include <err.h>
40#include <errno(*__errno()).h>
41#include <fts.h>
42#include <grp.h>
43#include <pwd.h>
44#include <stdio.h>
45#include <stdlib.h>
46#include <string.h>
47#include <time.h>
48#include <unistd.h>
49#include <limits.h>
50#include <util.h>
51
52#include "ls.h"
53#include "extern.h"
54
55static int printaname(FTSENT *, int, int);
56static void printlink(FTSENT *);
57static void printsize(int, off_t);
58static void printtime(time_t);
59static int printtype(mode_t);
60static int compute_columns(DISPLAY *, int *);
61
62#define IS_NOPRINT(p)((p)->fts_number == 1) ((p)->fts_number == NO_PRINT1)
63
64#define DATELEN64 64
65
66#define SECSPERDAY(24 * 60 * 60) (24 * 60 * 60)
67#define SIXMONTHS((24 * 60 * 60) * 365 / 2) (SECSPERDAY(24 * 60 * 60) * 365 / 2)
68
69void
70printscol(DISPLAY *dp)
71{
72 FTSENT *p;
73
74 for (p = dp->list; p; p = p->fts_link) {
75 if (IS_NOPRINT(p)((p)->fts_number == 1))
76 continue;
77 (void)printaname(p, dp->s_inode, dp->s_block);
78 (void)putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
79 }
80}
81
82void
83printlong(DISPLAY *dp)
84{
85 struct stat *sp;
86 FTSENT *p;
87 NAMES *np;
88 char buf[20];
89
90 if ((dp->list == NULL((void *)0) || dp->list->fts_level != FTS_ROOTLEVEL0) &&
91 (f_longform || f_size))
92 (void)printf("total %llu\n", howmany(dp->btotal, blocksize)(((dp->btotal) + ((blocksize) - 1)) / (blocksize)));
93
94 for (p = dp->list; p; p = p->fts_link) {
95 if (IS_NOPRINT(p)((p)->fts_number == 1))
96 continue;
97 sp = p->fts_statp;
98 if (f_inode)
99 (void)printf("%*llu ", dp->s_inode,
100 (unsigned long long)sp->st_ino);
101 if (f_size)
102 (void)printf("%*lld ", dp->s_block,
103 howmany((long long)sp->st_blocks, blocksize)((((long long)sp->st_blocks) + ((blocksize) - 1)) / (blocksize
))
);
104 (void)strmode(sp->st_mode, buf);
105 np = p->fts_pointer;
106 (void)printf("%s %*u ", buf, dp->s_nlink, sp->st_nlink);
107 if (!f_grouponly)
108 (void)printf("%-*s ", dp->s_user, np->user);
109 (void)printf("%-*s ", dp->s_group, np->group);
110 if (f_flags)
111 (void)printf("%-*s ", dp->s_flags, np->flags);
112 if (S_ISCHR(sp->st_mode)((sp->st_mode & 0170000) == 0020000) || S_ISBLK(sp->st_mode)((sp->st_mode & 0170000) == 0060000))
113 (void)printf("%*u, %*u ",
114 dp->s_major, major(sp->st_rdev)(((unsigned)(sp->st_rdev) >> 8) & 0xff),
115 dp->s_minor, minor(sp->st_rdev)((unsigned)((sp->st_rdev) & 0xff) | (((sp->st_rdev)
& 0xffff0000) >> 8))
);
116 else
117 printsize(dp->s_size, sp->st_size);
118 if (f_accesstime)
119 printtime(sp->st_atimest_atim.tv_sec);
120 else if (f_statustime)
121 printtime(sp->st_ctimest_ctim.tv_sec);
122 else
123 printtime(sp->st_mtimest_mtim.tv_sec);
124 (void)mbsprint(p->fts_name, 1);
125 if (f_type || (f_typedir && S_ISDIR(sp->st_mode)((sp->st_mode & 0170000) == 0040000)))
126 (void)printtype(sp->st_mode);
127 if (S_ISLNK(sp->st_mode)((sp->st_mode & 0170000) == 0120000))
128 printlink(p);
129 (void)putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
130 }
131}
132
133static int
134compute_columns(DISPLAY *dp, int *pnum)
135{
136 int colwidth;
137 extern int termwidth;
138 int mywidth;
139
140 colwidth = dp->maxlen;
141 if (f_inode)
142 colwidth += dp->s_inode + 1;
143 if (f_size)
144 colwidth += dp->s_block + 1;
145 if (f_type || f_typedir)
146 colwidth += 1;
147
148 colwidth += 1;
149 mywidth = termwidth + 1; /* no extra space for last column */
150
151 if (mywidth < 2 * colwidth) {
152 printscol(dp);
153 return (0);
154 }
155
156 *pnum = mywidth / colwidth;
157 return (mywidth / *pnum); /* spread out if possible */
158}
159
160void
161printcol(DISPLAY *dp)
162{
163 static FTSENT **array;
1
'array' initialized to a null pointer value
164 static int lastentries = -1;
165 FTSENT *p;
166 int base, chcnt, col, colwidth, num;
167 int numcols, numrows, row;
168
169 if ((colwidth = compute_columns(dp, &numcols)) == 0)
2
Assuming the condition is false
3
Taking false branch
170 return;
171 /*
172 * Have to do random access in the linked list -- build a table
173 * of pointers.
174 */
175 if (dp->entries > lastentries) {
4
Assuming 'lastentries' is >= field 'entries'
5
Taking false branch
176 FTSENT **a;
177
178 if ((a = reallocarray(array, dp->entries, sizeof(FTSENT *))) ==
179 NULL((void *)0)) {
180 free(array);
181 array = NULL((void *)0);
182 dp->entries = 0;
183 lastentries = -1;
184 warn(NULL((void *)0));
185 printscol(dp);
186 return;
187 }
188 lastentries = dp->entries;
189 array = a;
190 }
191 for (p = dp->list, num = 0; p; p = p->fts_link)
6
Loop condition is true. Entering loop body
192 if (p->fts_number != NO_PRINT1)
7
Assuming field 'fts_number' is not equal to NO_PRINT
8
Taking true branch
193 array[num++] = p;
9
Array access (from variable 'array') results in a null pointer dereference
194
195 numrows = num / numcols;
196 if (num % numcols)
197 ++numrows;
198
199 if ((dp->list == NULL((void *)0) || dp->list->fts_level != FTS_ROOTLEVEL0) &&
200 (f_longform || f_size))
201 (void)printf("total %llu\n", howmany(dp->btotal, blocksize)(((dp->btotal) + ((blocksize) - 1)) / (blocksize)));
202 for (row = 0; row < numrows; ++row) {
203 for (base = row, col = 0;;) {
204 chcnt = printaname(array[base], dp->s_inode, dp->s_block);
205 if ((base += numrows) >= num)
206 break;
207 if (++col == numcols)
208 break;
209 while (chcnt++ < colwidth)
210 putchar(' ')(!__isthreaded ? __sputc(' ', (&__sF[1])) : (putc)(' ', (
&__sF[1])))
;
211 }
212 (void)putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
213 }
214}
215
216/*
217 * print [inode] [size] name
218 * return # of characters printed, no trailing characters.
219 */
220static int
221printaname(FTSENT *p, int inodefield, int sizefield)
222{
223 struct stat *sp;
224 int chcnt;
225
226 sp = p->fts_statp;
227 chcnt = 0;
228 if (f_inode)
229 chcnt += printf("%*llu ", inodefield,
230 (unsigned long long)sp->st_ino);
231 if (f_size)
232 chcnt += printf("%*lld ", sizefield,
233 howmany((long long)sp->st_blocks, blocksize)((((long long)sp->st_blocks) + ((blocksize) - 1)) / (blocksize
))
);
234 chcnt += mbsprint(p->fts_name, 1);
235 if (f_type || (f_typedir && S_ISDIR(sp->st_mode)((sp->st_mode & 0170000) == 0040000)))
236 chcnt += printtype(sp->st_mode);
237 return (chcnt);
238}
239
240static void
241printtime(time_t ftime)
242{
243 char f_date[DATELEN64];
244 static time_t now;
245 static int now_set = 0;
246
247 if (! now_set) {
248 now = time(NULL((void *)0));
249 now_set = 1;
250 }
251
252 /*
253 * convert time to string, and print
254 */
255 if (strftime(f_date, sizeof(f_date), f_sectime ? "%b %e %H:%M:%S %Y" :
256 (ftime <= now - SIXMONTHS((24 * 60 * 60) * 365 / 2) || ftime > now) ? "%b %e %Y" :
257 "%b %e %H:%M", localtime(&ftime)) == 0)
258 f_date[0] = '\0';
259
260 printf("%s ", f_date);
261}
262
263void
264printacol(DISPLAY *dp)
265{
266 FTSENT *p;
267 int chcnt, col, colwidth;
268 int numcols;
269
270 if ( (colwidth = compute_columns(dp, &numcols)) == 0)
271 return;
272
273 if ((dp->list == NULL((void *)0) || dp->list->fts_level != FTS_ROOTLEVEL0) &&
274 (f_longform || f_size))
275 (void)printf("total %llu\n", howmany(dp->btotal, blocksize)(((dp->btotal) + ((blocksize) - 1)) / (blocksize)));
276 col = 0;
277 for (p = dp->list; p; p = p->fts_link) {
278 if (IS_NOPRINT(p)((p)->fts_number == 1))
279 continue;
280 if (col >= numcols) {
281 col = 0;
282 (void)putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
283 }
284 chcnt = printaname(p, dp->s_inode, dp->s_block);
285 col++;
286 if (col < numcols)
287 while (chcnt++ < colwidth)
288 (void)putchar(' ')(!__isthreaded ? __sputc(' ', (&__sF[1])) : (putc)(' ', (
&__sF[1])))
;
289 }
290 (void)putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
291}
292
293void
294printstream(DISPLAY *dp)
295{
296 extern int termwidth;
297 FTSENT *p;
298 int col;
299 int extwidth;
300
301 extwidth = 0;
302 if (f_inode)
303 extwidth += dp->s_inode + 1;
304 if (f_size)
305 extwidth += dp->s_block + 1;
306 if (f_type)
307 extwidth += 1;
308
309 for (col = 0, p = dp->list; p != NULL((void *)0); p = p->fts_link) {
310 if (IS_NOPRINT(p)((p)->fts_number == 1))
311 continue;
312 if (col > 0) {
313 (void)putchar(',')(!__isthreaded ? __sputc(',', (&__sF[1])) : (putc)(',', (
&__sF[1])))
, col++;
314 if (col + 1 + extwidth + mbsprint(p->fts_name, 0) >=
315 termwidth)
316 (void)putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
, col = 0;
317 else
318 (void)putchar(' ')(!__isthreaded ? __sputc(' ', (&__sF[1])) : (putc)(' ', (
&__sF[1])))
, col++;
319 }
320 col += printaname(p, dp->s_inode, dp->s_block);
321 }
322 (void)putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
323}
324
325static int
326printtype(mode_t mode)
327{
328 switch (mode & S_IFMT0170000) {
329 case S_IFDIR0040000:
330 (void)putchar('/')(!__isthreaded ? __sputc('/', (&__sF[1])) : (putc)('/', (
&__sF[1])))
;
331 return (1);
332 case S_IFIFO0010000:
333 (void)putchar('|')(!__isthreaded ? __sputc('|', (&__sF[1])) : (putc)('|', (
&__sF[1])))
;
334 return (1);
335 case S_IFLNK0120000:
336 (void)putchar('@')(!__isthreaded ? __sputc('@', (&__sF[1])) : (putc)('@', (
&__sF[1])))
;
337 return (1);
338 case S_IFSOCK0140000:
339 (void)putchar('=')(!__isthreaded ? __sputc('=', (&__sF[1])) : (putc)('=', (
&__sF[1])))
;
340 return (1);
341 }
342 if (mode & (S_IXUSR0000100 | S_IXGRP0000010 | S_IXOTH0000001)) {
343 (void)putchar('*')(!__isthreaded ? __sputc('*', (&__sF[1])) : (putc)('*', (
&__sF[1])))
;
344 return (1);
345 }
346 return (0);
347}
348
349static void
350printlink(FTSENT *p)
351{
352 int lnklen;
353 char name[PATH_MAX1024], path[PATH_MAX1024];
354
355 if (p->fts_level == FTS_ROOTLEVEL0)
356 (void)snprintf(name, sizeof(name), "%s", p->fts_name);
357 else
358 (void)snprintf(name, sizeof(name),
359 "%s/%s", p->fts_parent->fts_accpath, p->fts_name);
360 if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) {
361 (void)fprintf(stderr(&__sF[2]), "\nls: %s: %s\n", name, strerror(errno(*__errno())));
362 return;
363 }
364 path[lnklen] = '\0';
365 (void)printf(" -> ");
366 (void)mbsprint(path, 1);
367}
368
369static void
370printsize(int width, off_t bytes)
371{
372 char ret[FMT_SCALED_STRSIZE7];
373
374 if ((f_humanval) && (fmt_scaled(bytes, ret) != -1)) {
375 (void)printf("%*s ", width, ret);
376 return;
377 }
378 (void)printf("%*lld ", width, (long long)bytes);
379}