Bug Summary

File:src/usr.bin/paste/paste.c
Warning:line 171, column 2
Potential leak of memory pointed to by 'lp'

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 paste.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/paste/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/paste/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/paste/paste.c
1/* $OpenBSD: paste.c,v 1.26 2018/08/04 19:19:37 schwarze Exp $ */
2
3/*
4 * Copyright (c) 1989 The Regents of the University of California.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Adam S. Moskowitz of Menlo Consulting.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#include <sys/queue.h>
36#include <sys/types.h>
37#include <err.h>
38#include <errno(*__errno()).h>
39#include <limits.h>
40#include <stdio.h>
41#include <stdlib.h>
42#include <string.h>
43#include <unistd.h>
44
45char *delim;
46int delimcnt;
47
48int tr(char *);
49__dead__attribute__((__noreturn__)) void usage(void);
50void parallel(char **);
51void sequential(char **);
52
53int
54main(int argc, char *argv[])
55{
56 extern char *optarg;
57 extern int optind;
58 int ch, seq;
59
60 if (pledge("stdio rpath", NULL((void *)0)) == -1)
1
Assuming the condition is false
2
Taking false branch
61 err(1, "pledge");
62
63 seq = 0;
64 while ((ch = getopt(argc, argv, "d:s")) != -1) {
3
Assuming the condition is false
4
Loop condition is false. Execution continues on line 77
65 switch (ch) {
66 case 'd':
67 delimcnt = tr(delim = optarg);
68 break;
69 case 's':
70 seq = 1;
71 break;
72 case '?':
73 default:
74 usage();
75 }
76 }
77 argc -= optind;
78 argv += optind;
79
80 if (argc == 0)
5
Assuming 'argc' is not equal to 0
6
Taking false branch
81 usage();
82
83 if (delim == NULL((void *)0)) {
7
Assuming 'delim' is not equal to NULL
8
Taking false branch
84 delimcnt = 1;
85 delim = "\t";
86 }
87
88 if (seq
8.1
'seq' is 0
)
9
Taking false branch
89 sequential(argv);
90 else
91 parallel(argv);
10
Calling 'parallel'
92 return 0;
93}
94
95struct list {
96 SIMPLEQ_ENTRY(list)struct { struct list *sqe_next; } entries;
97 FILE *fp;
98 int cnt;
99 char *name;
100};
101
102void
103parallel(char **argv)
104{
105 SIMPLEQ_HEAD(, list)struct { struct list *sqh_first; struct list **sqh_last; } head = SIMPLEQ_HEAD_INITIALIZER(head){ ((void *)0), &(head).sqh_first };
106 struct list *lp;
107 char *line, *p;
108 size_t linesize;
109 ssize_t len;
110 int cnt;
111 int opencnt, output;
112 char ch;
113
114 for (cnt = 0; (p = *argv) != NULL((void *)0); ++argv, ++cnt) {
11
Assuming the condition is true
12
Loop condition is true. Entering loop body
20
Assuming the condition is false
21
Loop condition is false. Execution continues on line 127
115 if ((lp = malloc(sizeof(*lp))) == NULL((void *)0))
13
Memory is allocated
14
Assuming the condition is false
15
Taking false branch
116 err(1, NULL((void *)0));
117
118 if (p[0] == '-' && p[1] == '\0')
16
Assuming the condition is false
119 lp->fp = stdin(&__sF[0]);
120 else if ((lp->fp = fopen(p, "r")) == NULL((void *)0))
17
Assuming the condition is false
18
Taking false branch
121 err(1, "%s", p);
122 lp->cnt = cnt;
123 lp->name = p;
124 SIMPLEQ_INSERT_TAIL(&head, lp, entries)do { (lp)->entries.sqe_next = ((void *)0); *(&head)->
sqh_last = (lp); (&head)->sqh_last = &(lp)->entries
.sqe_next; } while (0)
;
19
Loop condition is false. Exiting loop
125 }
126
127 line = NULL((void *)0);
128 linesize = 0;
129
130 for (opencnt = cnt; opencnt;) {
22
Loop condition is true. Entering loop body
34
Loop condition is false. Execution continues on line 171
131 output = 0;
132 SIMPLEQ_FOREACH(lp, &head, entries)for((lp) = ((&head)->sqh_first); (lp) != ((void *)0); (
lp) = ((lp)->entries.sqe_next))
{
23
Loop condition is true. Entering loop body
133 if (lp->fp
23.1
Field 'fp' is not equal to NULL
== NULL((void *)0)) {
24
Taking false branch
134 if (output && lp->cnt &&
135 (ch = delim[(lp->cnt - 1) % delimcnt]))
136 putchar(ch)(!__isthreaded ? __sputc(ch, (&__sF[1])) : (putc)(ch, (&
__sF[1])))
;
137 continue;
138 }
139 if ((len = getline(&line, &linesize, lp->fp)) == -1) {
25
Assuming the condition is true
26
Taking true branch
140 if (ferror(lp->fp)(!__isthreaded ? (((lp->fp)->_flags & 0x0040) != 0)
: (ferror)(lp->fp))
)
27
Assuming '__isthreaded' is not equal to 0
28
'?' condition is false
29
Assuming the condition is false
30
Taking false branch
141 err(1, "%s", lp->fp == stdin(&__sF[0]) ?
142 "getline" : lp->name);
143 if (--opencnt == 0)
31
Taking true branch
144 break;
32
Execution continues on line 168
145 if (lp->fp != stdin(&__sF[0]))
146 fclose(lp->fp);
147 lp->fp = NULL((void *)0);
148 if (output && lp->cnt &&
149 (ch = delim[(lp->cnt - 1) % delimcnt]))
150 putchar(ch)(!__isthreaded ? __sputc(ch, (&__sF[1])) : (putc)(ch, (&
__sF[1])))
;
151 continue;
152 }
153 if (line[len - 1] == '\n')
154 line[len - 1] = '\0';
155 /*
156 * make sure that we don't print any delimiters
157 * unless there's a non-empty file.
158 */
159 if (!output) {
160 output = 1;
161 for (cnt = 0; cnt < lp->cnt; ++cnt)
162 if ((ch = delim[cnt % delimcnt]))
163 putchar(ch)(!__isthreaded ? __sputc(ch, (&__sF[1])) : (putc)(ch, (&
__sF[1])))
;
164 } else if ((ch = delim[(lp->cnt - 1) % delimcnt]))
165 putchar(ch)(!__isthreaded ? __sputc(ch, (&__sF[1])) : (putc)(ch, (&
__sF[1])))
;
166 fputs(line, stdout(&__sF[1]));
167 }
168 if (output
32.1
'output' is 0
)
33
Taking false branch
169 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
170 }
171 free(line);
35
Potential leak of memory pointed to by 'lp'
172}
173
174void
175sequential(char **argv)
176{
177 FILE *fp;
178 char *line, *p;
179 size_t linesize;
180 ssize_t len;
181 int cnt;
182
183 line = NULL((void *)0);
184 linesize = 0;
185 for (; (p = *argv) != NULL((void *)0); ++argv) {
186 if (p[0] == '-' && p[1] == '\0')
187 fp = stdin(&__sF[0]);
188 else if ((fp = fopen(p, "r")) == NULL((void *)0)) {
189 warn("%s", p);
190 continue;
191 }
192 cnt = -1;
193 while ((len = getline(&line, &linesize, fp)) != -1) {
194 if (line[len - 1] == '\n')
195 line[len - 1] = '\0';
196 if (cnt >= 0)
197 putchar(delim[cnt])(!__isthreaded ? __sputc(delim[cnt], (&__sF[1])) : (putc)
(delim[cnt], (&__sF[1])))
;
198 if (++cnt == delimcnt)
199 cnt = 0;
200 fputs(line, stdout(&__sF[1]));
201 }
202 if (ferror(fp)(!__isthreaded ? (((fp)->_flags & 0x0040) != 0) : (ferror
)(fp))
)
203 err(1, "%s", fp == stdin(&__sF[0]) ? "getline" : p);
204 if (cnt >= 0)
205 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
206 if (fp != stdin(&__sF[0]))
207 fclose(fp);
208 }
209 free(line);
210}
211
212int
213tr(char *arg)
214{
215 int cnt;
216 char ch, *p;
217
218 for (p = arg, cnt = 0; (ch = *p++) != '\0'; ++arg, ++cnt) {
219 if (ch == '\\') {
220 switch (ch = *p++) {
221 case 'n':
222 *arg = '\n';
223 break;
224 case 't':
225 *arg = '\t';
226 break;
227 case '0':
228 *arg = '\0';
229 break;
230 default:
231 *arg = ch;
232 break;
233 }
234 } else
235 *arg = ch;
236 }
237
238 if (cnt == 0)
239 errx(1, "no delimiters specified");
240 return cnt;
241}
242
243__dead__attribute__((__noreturn__)) void
244usage(void)
245{
246 extern char *__progname;
247 fprintf(stderr(&__sF[2]), "usage: %s [-s] [-d list] file ...\n", __progname);
248 exit(1);
249}