Bug Summary

File:src/usr.bin/patch/ed.c
Warning:line 166, column 2
Value stored to 'fsm' is never read

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 ed.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/patch/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/patch/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/patch/ed.c
1/* $OpenBSD: ed.c,v 1.4 2019/12/02 22:17:32 jca Exp $ */
2
3/*
4 * Copyright (c) 2015 Tobias Stoeckmann <tobias@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/queue.h>
20#include <sys/stat.h>
21
22#include <ctype.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26
27#include "common.h"
28#include "util.h"
29#include "pch.h"
30#include "inp.h"
31
32/* states of finite state machine */
33#define FSM_CMD1 1
34#define FSM_A2 2
35#define FSM_C3 3
36#define FSM_D4 4
37#define FSM_I5 5
38#define FSM_S6 6
39
40#define SRC_INP1 1 /* line's origin is input file */
41#define SRC_PCH2 2 /* line's origin is patch file */
42
43#define S_PATTERN"/.//" "/.//"
44
45static void init_lines(void);
46static void free_lines(void);
47static struct ed_line *get_line(LINENUM);
48static struct ed_line *create_line(off_t);
49static int valid_addr(LINENUM, LINENUM);
50static int get_command(void);
51static void write_lines(char *);
52
53LIST_HEAD(ed_head, ed_line)struct ed_head { struct ed_line *lh_first; } head;
54struct ed_line {
55 LIST_ENTRY(ed_line)struct { struct ed_line *le_next; struct ed_line **le_prev; } entries;
56 int src;
57 unsigned long subst;
58 union {
59 LINENUM lineno;
60 off_t seek;
61 } pos;
62};
63
64static LINENUM first_addr;
65static LINENUM second_addr;
66static LINENUM line_count;
67static struct ed_line *cline; /* current line */
68
69void
70do_ed_script(void)
71{
72 off_t linepos;
73 struct ed_line *nline;
74 LINENUM i, range;
75 int fsm;
76
77 init_lines();
78 cline = NULL((void *)0);
79 fsm = FSM_CMD1;
80
81 for (;;) {
82 linepos = ftello(pfp);
83 if (pgetline(&buf, &bufsz, pfp) == -1)
84 break;
85 p_input_line++;
86
87 if (fsm == FSM_CMD1) {
88 if ((fsm = get_command()) == -1)
89 break;
90
91 switch (fsm) {
92 case FSM_C3:
93 case FSM_D4:
94 /* delete lines in specified range */
95 if (second_addr == -1)
96 range = 1;
97 else
98 range = second_addr - first_addr + 1;
99 for (i = 0; i < range; i++) {
100 nline = LIST_NEXT(cline, entries)((cline)->entries.le_next);
101 LIST_REMOVE(cline, entries)do { if ((cline)->entries.le_next != ((void *)0)) (cline)->
entries.le_next->entries.le_prev = (cline)->entries.le_prev
; *(cline)->entries.le_prev = (cline)->entries.le_next;
; ; } while (0)
;
102 free(cline);
103 cline = nline;
104 line_count--;
105 }
106 cline = get_line(first_addr - 1);
107 fsm = (fsm == FSM_C3) ? FSM_A2 : FSM_CMD1;
108 break;
109 case FSM_S6:
110 cline->subst++;
111 fsm = FSM_CMD1;
112 break;
113 default:
114 break;
115 }
116
117 continue;
118 }
119
120 if (strcmp(buf, ".\n") == 0) {
121 fsm = FSM_CMD1;
122 continue;
123 }
124
125 nline = create_line(linepos);
126 if (cline == NULL((void *)0))
127 LIST_INSERT_HEAD(&head, nline, entries)do { if (((nline)->entries.le_next = (&head)->lh_first
) != ((void *)0)) (&head)->lh_first->entries.le_prev
= &(nline)->entries.le_next; (&head)->lh_first
= (nline); (nline)->entries.le_prev = &(&head)->
lh_first; } while (0)
;
128 else if (fsm == FSM_A2)
129 LIST_INSERT_AFTER(cline, nline, entries)do { if (((nline)->entries.le_next = (cline)->entries.le_next
) != ((void *)0)) (cline)->entries.le_next->entries.le_prev
= &(nline)->entries.le_next; (cline)->entries.le_next
= (nline); (nline)->entries.le_prev = &(cline)->entries
.le_next; } while (0)
;
130 else
131 LIST_INSERT_BEFORE(cline, nline, entries)do { (nline)->entries.le_prev = (cline)->entries.le_prev
; (nline)->entries.le_next = (cline); *(cline)->entries
.le_prev = (nline); (cline)->entries.le_prev = &(nline
)->entries.le_next; } while (0)
;
132 cline = nline;
133 line_count++;
134 fsm = FSM_A2;
135 }
136
137 next_intuit_at(linepos, p_input_line);
138
139 if (skip_rest_of_patch) {
140 free_lines();
141 return;
142 }
143
144 write_lines(TMPOUTNAME);
145 free_lines();
146
147 ignore_signals();
148 if (!check_only) {
149 if (move_file(TMPOUTNAME, outname) < 0) {
150 toutkeep = true1;
151 chmod(TMPOUTNAME, filemode);
152 } else
153 chmod(outname, filemode);
154 }
155 set_signals(1);
156}
157
158static int
159get_command(void)
160{
161 char *p;
162 LINENUM min_addr;
163 int fsm;
164
165 min_addr = 0;
166 fsm = -1;
Value stored to 'fsm' is never read
167 p = buf;
168
169 /* maybe garbage encountered at end of patch */
170 if (!isdigit((unsigned char)*p))
171 return -1;
172
173 first_addr = strtolinenum(buf, &p);
174 second_addr = (*p == ',') ? strtolinenum(p + 1, &p) : -1;
175
176 switch (*p++) {
177 case 'a':
178 if (second_addr != -1)
179 fatal("invalid address at line %ld: %s",
180 p_input_line, buf);
181 fsm = FSM_A2;
182 break;
183 case 'c':
184 fsm = FSM_C3;
185 min_addr = 1;
186 break;
187 case 'd':
188 fsm = FSM_D4;
189 min_addr = 1;
190 break;
191 case 'i':
192 if (second_addr != -1)
193 fatal("invalid address at line %ld: %s",
194 p_input_line, buf);
195 fsm = FSM_I5;
196 break;
197 case 's':
198 if (second_addr != -1)
199 fatal("unsupported address range at line %ld: %s",
200 p_input_line, buf);
201 if (strncmp(p, S_PATTERN"/.//", sizeof(S_PATTERN"/.//") - 1) != 0)
202 fatal("unsupported substitution at "
203 "line %ld: %s", p_input_line, buf);
204 p += sizeof(S_PATTERN"/.//") - 1;
205 fsm = FSM_S6;
206 min_addr = 1;
207 break;
208 default:
209 return -1;
210 /* NOTREACHED */
211 }
212
213 if (*p != '\n')
214 return -1;
215
216 if (!valid_addr(first_addr, min_addr) ||
217 (second_addr != -1 && !valid_addr(second_addr, first_addr)))
218 fatal("invalid address at line %ld: %s", p_input_line, buf);
219
220 cline = get_line(first_addr);
221
222 return fsm;
223}
224
225static void
226write_lines(char *filename)
227{
228 FILE *ofp;
229 char *p;
230 struct ed_line *line;
231 off_t linepos;
232
233 linepos = ftello(pfp);
234 ofp = fopen(filename, "w");
235 if (ofp == NULL((void *)0))
236 pfatal("can't create %s", filename);
237
238 LIST_FOREACH(line, &head, entries)for((line) = ((&head)->lh_first); (line)!= ((void *)0)
; (line) = ((line)->entries.le_next))
{
239 if (line->src == SRC_INP1) {
240 p = ifetch(line->pos.lineno, 0);
241 /* Note: string is not NUL terminated. */
242 for (; *p != '\n'; p++)
243 if (line->subst != 0)
244 line->subst--;
245 else
246 putc(*p, ofp)(!__isthreaded ? __sputc(*p, ofp) : (putc)(*p, ofp));
247 putc('\n', ofp)(!__isthreaded ? __sputc('\n', ofp) : (putc)('\n', ofp));
248 } else if (line->src == SRC_PCH2) {
249 fseeko(pfp, line->pos.seek, SEEK_SET0);
250 if (pgetline(&buf, &bufsz, pfp) == -1)
251 fatal("unexpected end of file");
252 p = buf;
253 if (line->subst != 0)
254 for (; *p != '\0' && *p != '\n'; p++)
255 if (line->subst-- == 0)
256 break;
257 fputs(p, ofp);
258 if (strchr(p, '\n') == NULL((void *)0))
259 putc('\n', ofp)(!__isthreaded ? __sputc('\n', ofp) : (putc)('\n', ofp));
260 }
261 }
262 fclose(ofp);
263
264 /* restore patch file position to match p_input_line */
265 fseeko(pfp, linepos, SEEK_SET0);
266}
267
268/* initialize list with input file */
269static void
270init_lines(void)
271{
272 struct ed_line *line;
273 LINENUM i;
274
275 LIST_INIT(&head)do { ((&head)->lh_first) = ((void *)0); } while (0);
276 for (i = input_lines; i > 0; i--) {
277 line = malloc(sizeof(*line));
278 if (line == NULL((void *)0))
279 fatal("cannot allocate memory");
280 line->src = SRC_INP1;
281 line->subst = 0;
282 line->pos.lineno = i;
283 LIST_INSERT_HEAD(&head, line, entries)do { if (((line)->entries.le_next = (&head)->lh_first
) != ((void *)0)) (&head)->lh_first->entries.le_prev
= &(line)->entries.le_next; (&head)->lh_first =
(line); (line)->entries.le_prev = &(&head)->lh_first
; } while (0)
;
284 }
285 line_count = input_lines;
286}
287
288static void
289free_lines(void)
290{
291 struct ed_line *line;
292
293 while (!LIST_EMPTY(&head)(((&head)->lh_first) == ((void *)0))) {
294 line = LIST_FIRST(&head)((&head)->lh_first);
295 LIST_REMOVE(line, entries)do { if ((line)->entries.le_next != ((void *)0)) (line)->
entries.le_next->entries.le_prev = (line)->entries.le_prev
; *(line)->entries.le_prev = (line)->entries.le_next; ;
; } while (0)
;
296 free(line);
297 }
298}
299
300static struct ed_line *
301get_line(LINENUM lineno)
302{
303 struct ed_line *line;
304 LINENUM i;
305
306 if (lineno == 0)
307 return NULL((void *)0);
308
309 i = 0;
310 LIST_FOREACH(line, &head, entries)for((line) = ((&head)->lh_first); (line)!= ((void *)0)
; (line) = ((line)->entries.le_next))
311 if (++i == lineno)
312 return line;
313
314 return NULL((void *)0);
315}
316
317static struct ed_line *
318create_line(off_t seek)
319{
320 struct ed_line *line;
321
322 line = malloc(sizeof(*line));
323 if (line == NULL((void *)0))
324 fatal("cannot allocate memory");
325 line->src = SRC_PCH2;
326 line->subst = 0;
327 line->pos.seek = seek;
328
329 return line;
330}
331
332static int
333valid_addr(LINENUM lineno, LINENUM min)
334{
335 return lineno >= min && lineno <= line_count;
336}