Bug Summary

File:src/usr.bin/lam/lam.c
Warning:line 137, column 8
Dereference of null pointer (loaded from variable 'p')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name lam.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 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -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/usr.bin/lam/obj -resource-dir /usr/local/lib/clang/13.0.0 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.bin/lam/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -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/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.bin/lam/lam.c
1/* $OpenBSD: lam.c,v 1.24 2021/12/03 15:15:22 deraadt Exp $ */
2/* $NetBSD: lam.c,v 1.2 1994/11/14 20:27:42 jtc Exp $ */
3
4/*-
5 * Copyright (c) 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33/*
34 * lam - laminate files
35 * Author: John Kunze, UCB
36 */
37
38#include <sys/types.h>
39
40#include <ctype.h>
41#include <err.h>
42#include <locale.h>
43#include <stdio.h>
44#include <stdlib.h>
45#include <limits.h>
46#include <string.h>
47#include <unistd.h>
48
49#define BIGBUFSIZ5 * 1024 5 * BUFSIZ1024
50
51struct openfile { /* open file structure */
52 FILE *fp; /* file pointer */
53 int minwidth; /* pad this column to this width */
54 int maxwidth; /* truncate this column */
55 short eof; /* eof flag */
56 short pad; /* pad flag for missing columns */
57 char eol; /* end of line character */
58 char align; /* '0' for zero fill, '-' for left align */
59 char *sepstring; /* string to print before each line */
60} *input;
61int inputsize; /* number of openfile entries */
62
63int output; /* line output produced */
64int nofinalnl; /* normally append \n to each output line */
65char line[BIGBUFSIZ5 * 1024];
66char *linep;
67
68int mbswidth_truncate(char *, int); /* utf8.c */
69
70void usage(void);
71char *gatherline(struct openfile *);
72void getargs(int, char *[]);
73char *pad(struct openfile *);
74
75int
76main(int argc, char *argv[])
77{
78 int i;
79
80 setlocale(LC_CTYPE2, "");
81
82 if (pledge("stdio rpath", NULL((void *)0)) == -1)
1
Assuming the condition is false
2
Taking false branch
83 err(1, "pledge");
84
85 getargs(argc, argv);
3
Calling 'getargs'
86 if (inputsize == 0)
87 usage();
88
89 if (pledge("stdio", NULL((void *)0)) == -1)
90 err(1, "pledge");
91
92 /* Concatenate lines from each file, then print. */
93 for (;;) {
94 linep = line;
95 /*
96 * For each file that has a line to print, output is
97 * incremented. Thus if numfiles is 0, we are done.
98 */
99 output = 0;
100 for (i = 0; i < inputsize && input[i].fp != NULL((void *)0); i++)
101 linep = gatherline(&input[i]);
102 if (output == 0)
103 exit(0);
104 fputs(line, stdout(&__sF[1]));
105 /* Print terminating -s argument. */
106 fputs(input[i].sepstring, stdout(&__sF[1]));
107 if (!nofinalnl)
108 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
109 }
110}
111
112void
113getargs(int argc, char *argv[])
114{
115 struct openfile *ip;
116 const char *errstr;
117 char *p, *q;
118 void *tmp;
119 int ch, P, S, F, T;
120
121 input = calloc(inputsize+1, sizeof *input);
122 if (input == NULL((void *)0))
4
Assuming 'input' is not equal to NULL
5
Taking false branch
123 errx(1, "too many files");
124 ip = &input[inputsize];
125
126 P = S = F = T = 0; /* capitalized options */
127 while (optind
9.1
'optind' is < 'argc'
< argc
) {
6
Assuming 'optind' is < 'argc'
7
Loop condition is true. Entering loop body
10
Loop condition is true. Entering loop body
27
Assuming 'optind' is < 'argc'
28
Loop condition is true. Entering loop body
128 switch (ch = getopt(argc, argv, "F:f:P:p:S:s:T:t:")) {
8
Control jumps to 'case 83:' at line 159
11
Control jumps to 'case -1:' at line 170
29
Control jumps to 'case 102:' at line 133
129 case 'P': case 'p':
130 P = (ch == 'P');
131 ip->pad = 1;
132 /* FALLTHROUGH */
133 case 'F': case 'f':
134 F = (ch == 'F');
135 /* Validate format string argument. */
136 p = optarg;
30
Null pointer value stored to 'p'
137 if (*p == '0' || *p == '-')
31
Dereference of null pointer (loaded from variable 'p')
138 ip->align = *p++;
139 else
140 ip->align = ' ';
141 if ((q = strchr(p, '.')) != NULL((void *)0))
142 *q++ = '\0';
143 if (*p != '\0') {
144 ip->minwidth = strtonum(p, 1, INT_MAX2147483647,
145 &errstr);
146 if (errstr != NULL((void *)0))
147 errx(1, "minimum width is %s: %s",
148 errstr, p);
149 }
150 if (q != NULL((void *)0)) {
151 ip->maxwidth = strtonum(q, 1, INT_MAX2147483647,
152 &errstr);
153 if (errstr != NULL((void *)0))
154 errx(1, "maximum width is %s: %s",
155 errstr, q);
156 } else
157 ip->maxwidth = INT_MAX2147483647;
158 break;
159 case 'S': case 's':
160 S = (ch == 'S');
161 ip->sepstring = optarg;
162 break;
9
Execution continues on line 127
163 case 'T': case 't':
164 T = (ch == 'T');
165 if (strlen(optarg) != 1)
166 usage();
167 ip->eol = optarg[0];
168 nofinalnl = 1;
169 break;
170 case -1:
171 if (optind
11.1
'optind' is < 'argc'
>= argc)
12
Taking false branch
172 break; /* to support "--" */
173 /* This is a file, not a flag. */
174 if (strcmp(argv[optind], "-") == 0)
13
Assuming the condition is false
14
Taking false branch
175 ip->fp = stdin(&__sF[0]);
176 else if ((ip->fp = fopen(argv[optind], "r")) == NULL((void *)0))
15
Assuming the condition is false
16
Taking false branch
177 err(1, "%s", argv[optind]);
178 ip->pad = P;
179 if (ip->sepstring == NULL((void *)0))
17
Assuming field 'sepstring' is equal to NULL
18
Taking true branch
180 ip->sepstring = S
18.1
'S' is 1
? (ip-1)->sepstring : "";
19
'?' condition is true
181 if (ip->eol == '\0')
20
Assuming the condition is false
21
Taking false branch
182 ip->eol = T ? (ip-1)->eol : '\n';
183 if (ip->align == '\0') {
22
Assuming the condition is false
23
Taking false branch
184 if (F || P) {
185 ip->align = (ip-1)->align;
186 ip->minwidth = (ip-1)->minwidth;
187 ip->maxwidth = (ip-1)->maxwidth;
188 } else
189 ip->maxwidth = INT_MAX2147483647;
190 }
191
192 ++inputsize;
193
194 /* Prepare for next file argument */
195 tmp = recallocarray(input, inputsize,
196 inputsize+1, sizeof *input);
197 if (tmp == NULL((void *)0))
24
Assuming 'tmp' is not equal to NULL
25
Taking false branch
198 errx(1, "too many files");
199 input = tmp;
200 ip = &input[inputsize];
201 optind++;
202 break;
26
Execution continues on line 127
203 default:
204 usage();
205 /* NOTREACHED */
206 }
207 }
208 ip->fp = NULL((void *)0);
209 if (ip->sepstring == NULL((void *)0))
210 ip->sepstring = "";
211}
212
213char *
214pad(struct openfile *ip)
215{
216 size_t n;
217 char *lp = linep;
218 int i = 0;
219
220 n = strlcpy(lp, ip->sepstring, line + sizeof(line) - lp);
221 lp += (n < line + sizeof(line) - lp) ? n : strlen(lp);
222 if (ip->pad)
223 while (i++ < ip->minwidth && lp + 1 < line + sizeof(line))
224 *lp++ = ' ';
225 *lp = '\0';
226 return (lp);
227}
228
229/*
230 * Grab line from file, appending to linep. Increments printed if file
231 * is still open.
232 */
233char *
234gatherline(struct openfile *ip)
235{
236 size_t n;
237 char s[BUFSIZ1024];
238 char *p;
239 char *lp = linep;
240 char *end = s + BUFSIZ1024 - 1;
241 int c, width;
242
243 if (ip->eof)
244 return (pad(ip));
245 for (p = s; (c = fgetc(ip->fp)) != EOF(-1) && p < end; p++)
246 if ((*p = c) == ip->eol)
247 break;
248 *p = '\0';
249 if (c == EOF(-1)) {
250 ip->eof = 1;
251 if (ip->fp == stdin(&__sF[0]))
252 fclose(stdin(&__sF[0]));
253 return (pad(ip));
254 }
255 /* Something will be printed. */
256 output++;
257 n = strlcpy(lp, ip->sepstring, line + sizeof(line) - lp);
258 lp += (n < line + sizeof(line) - lp) ? n : strlen(lp);
259 width = mbswidth_truncate(s, ip->maxwidth);
260 if (ip->align != '-')
261 while (width++ < ip->minwidth && lp + 1 < line + sizeof(line))
262 *lp++ = ip->align;
263 n = strlcpy(lp, s, line + sizeof(line) - lp);
264 lp += (n < line + sizeof(line) - lp) ? n : strlen(lp);
265 if (ip->align == '-')
266 while (width++ < ip->minwidth && lp + 1 < line + sizeof(line))
267 *lp++ = ' ';
268 *lp = '\0';
269 return (lp);
270}
271
272void
273usage(void)
274{
275 extern char *__progname;
276
277 fprintf(stderr(&__sF[2]),
278 "usage: %s [-F|f min.max] [-P|p min.max] [-S|s sepstring] [-T|t c] file ...\n",
279 __progname);
280 exit(1);
281}