Bug Summary

File:src/usr.bin/paste/paste.c
Warning:line 170, 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.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name paste.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/usr.bin/paste/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/usr.bin/paste/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/usr.bin/paste/paste.c
1/* $OpenBSD: paste.c,v 1.27 2022/12/04 23:50:49 cheloha 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 76
65 switch (ch) {
66 case 'd':
67 delimcnt = tr(delim = optarg);
68 break;
69 case 's':
70 seq = 1;
71 break;
72 default:
73 usage();
74 }
75 }
76 argc -= optind;
77 argv += optind;
78
79 if (argc == 0)
5
Assuming 'argc' is not equal to 0
6
Taking false branch
80 usage();
81
82 if (delim == NULL((void *)0)) {
7
Assuming 'delim' is not equal to NULL
8
Taking false branch
83 delimcnt = 1;
84 delim = "\t";
85 }
86
87 if (seq
8.1
'seq' is 0
)
9
Taking false branch
88 sequential(argv);
89 else
90 parallel(argv);
10
Calling 'parallel'
91 return 0;
92}
93
94struct list {
95 SIMPLEQ_ENTRY(list)struct { struct list *sqe_next; } entries;
96 FILE *fp;
97 int cnt;
98 char *name;
99};
100
101void
102parallel(char **argv)
103{
104 SIMPLEQ_HEAD(, list)struct { struct list *sqh_first; struct list **sqh_last; } head = SIMPLEQ_HEAD_INITIALIZER(head){ ((void *)0), &(head).sqh_first };
105 struct list *lp;
106 char *line, *p;
107 size_t linesize;
108 ssize_t len;
109 int cnt;
110 int opencnt, output;
111 char ch;
112
113 for (cnt = 0; (p = *argv) != NULL((void *)0); ++argv, ++cnt) {
11
Assuming the condition is true
12
Loop condition is true. Entering loop body
19
Assuming the condition is false
20
Loop condition is false. Execution continues on line 126
114 if ((lp = malloc(sizeof(*lp))) == NULL((void *)0))
13
Memory is allocated
14
Assuming the condition is false
115 err(1, NULL((void *)0));
116
117 if (p[0] == '-' && p[1] == '\0')
15
Assuming the condition is false
118 lp->fp = stdin(&__sF[0]);
119 else if ((lp->fp = fopen(p, "r")) == NULL((void *)0))
16
Assuming the condition is false
17
Taking false branch
120 err(1, "%s", p);
121 lp->cnt = cnt;
122 lp->name = p;
123 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)
;
18
Loop condition is false. Exiting loop
124 }
125
126 line = NULL((void *)0);
127 linesize = 0;
128
129 for (opencnt = cnt; opencnt;) {
21
Loop condition is true. Entering loop body
33
Loop condition is false. Execution continues on line 170
130 output = 0;
131 SIMPLEQ_FOREACH(lp, &head, entries)for((lp) = ((&head)->sqh_first); (lp) != ((void *)0); (
lp) = ((lp)->entries.sqe_next))
{
22
Loop condition is true. Entering loop body
132 if (lp->fp
22.1
Field 'fp' is not equal to NULL
== NULL((void *)0)) {
23
Taking false branch
133 if (output && lp->cnt &&
134 (ch = delim[(lp->cnt - 1) % delimcnt]))
135 putchar(ch)(!__isthreaded ? __sputc(ch, (&__sF[1])) : (putc)(ch, (&
__sF[1])))
;
136 continue;
137 }
138 if ((len = getline(&line, &linesize, lp->fp)) == -1) {
24
Assuming the condition is true
25
Taking true branch
139 if (ferror(lp->fp)(!__isthreaded ? (((lp->fp)->_flags & 0x0040) != 0)
: (ferror)(lp->fp))
)
26
Assuming '__isthreaded' is not equal to 0
27
'?' condition is false
28
Assuming the condition is false
29
Taking false branch
140 err(1, "%s", lp->fp == stdin(&__sF[0]) ?
141 "getline" : lp->name);
142 if (--opencnt == 0)
30
Taking true branch
143 break;
144 if (lp->fp != stdin(&__sF[0]))
145 fclose(lp->fp);
146 lp->fp = NULL((void *)0);
147 if (output && lp->cnt &&
148 (ch = delim[(lp->cnt - 1) % delimcnt]))
149 putchar(ch)(!__isthreaded ? __sputc(ch, (&__sF[1])) : (putc)(ch, (&
__sF[1])))
;
150 continue;
151 }
152 if (line[len - 1] == '\n')
153 line[len - 1] = '\0';
154 /*
155 * make sure that we don't print any delimiters
156 * unless there's a non-empty file.
157 */
158 if (!output) {
159 output = 1;
160 for (cnt = 0; cnt < lp->cnt; ++cnt)
161 if ((ch = delim[cnt % delimcnt]))
162 putchar(ch)(!__isthreaded ? __sputc(ch, (&__sF[1])) : (putc)(ch, (&
__sF[1])))
;
163 } else if ((ch = delim[(lp->cnt - 1) % delimcnt]))
164 putchar(ch)(!__isthreaded ? __sputc(ch, (&__sF[1])) : (putc)(ch, (&
__sF[1])))
;
165 fputs(line, stdout(&__sF[1]));
166 }
167 if (output
31.1
'output' is 0
)
31
Execution continues on line 167
32
Taking false branch
168 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
169 }
170 free(line);
34
Potential leak of memory pointed to by 'lp'
171}
172
173void
174sequential(char **argv)
175{
176 FILE *fp;
177 char *line, *p;
178 size_t linesize;
179 ssize_t len;
180 int cnt;
181
182 line = NULL((void *)0);
183 linesize = 0;
184 for (; (p = *argv) != NULL((void *)0); ++argv) {
185 if (p[0] == '-' && p[1] == '\0')
186 fp = stdin(&__sF[0]);
187 else if ((fp = fopen(p, "r")) == NULL((void *)0)) {
188 warn("%s", p);
189 continue;
190 }
191 cnt = -1;
192 while ((len = getline(&line, &linesize, fp)) != -1) {
193 if (line[len - 1] == '\n')
194 line[len - 1] = '\0';
195 if (cnt >= 0)
196 putchar(delim[cnt])(!__isthreaded ? __sputc(delim[cnt], (&__sF[1])) : (putc)
(delim[cnt], (&__sF[1])))
;
197 if (++cnt == delimcnt)
198 cnt = 0;
199 fputs(line, stdout(&__sF[1]));
200 }
201 if (ferror(fp)(!__isthreaded ? (((fp)->_flags & 0x0040) != 0) : (ferror
)(fp))
)
202 err(1, "%s", fp == stdin(&__sF[0]) ? "getline" : p);
203 if (cnt >= 0)
204 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
205 if (fp != stdin(&__sF[0]))
206 fclose(fp);
207 }
208 free(line);
209}
210
211int
212tr(char *arg)
213{
214 int cnt;
215 char ch, *p;
216
217 for (p = arg, cnt = 0; (ch = *p++) != '\0'; ++arg, ++cnt) {
218 if (ch == '\\') {
219 switch (ch = *p++) {
220 case 'n':
221 *arg = '\n';
222 break;
223 case 't':
224 *arg = '\t';
225 break;
226 case '0':
227 *arg = '\0';
228 break;
229 default:
230 *arg = ch;
231 break;
232 }
233 } else
234 *arg = ch;
235 }
236
237 if (cnt == 0)
238 errx(1, "no delimiters specified");
239 return cnt;
240}
241
242__dead__attribute__((__noreturn__)) void
243usage(void)
244{
245 extern char *__progname;
246 fprintf(stderr(&__sF[2]), "usage: %s [-s] [-d list] file ...\n", __progname);
247 exit(1);
248}