Bug Summary

File:src/games/worm/worm.c
Warning:line 215, column 7
Assigned value is garbage or undefined

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 worm.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/games/worm/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/games/worm/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/games/worm/worm.c
1/* $OpenBSD: worm.c,v 1.39 2018/08/24 11:14:49 mestre Exp $ */
2
3/*
4 * Copyright (c) 1980, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * Worm. Written by Michael Toy
34 * UCSC
35 */
36
37#include <ctype.h>
38#include <curses.h>
39#include <err.h>
40#include <poll.h>
41#include <signal.h>
42#include <stdlib.h>
43#include <unistd.h>
44
45#define HEAD'@' '@'
46#define BODY'o' 'o'
47#define LENGTH7 7
48#define RUNLEN8 8
49#define CNTRL(p)(p-'A'+1) (p-'A'+1)
50
51WINDOW *tv;
52WINDOW *stw;
53struct body {
54 int x;
55 int y;
56 struct body *prev;
57 struct body *next;
58} *head, *tail, goody;
59int growing = 0;
60int growthscale = 1;
61int running = 0;
62int slow = 0;
63int score = 0;
64int start_len = LENGTH7;
65int visible_len;
66int lastch;
67char outbuf[BUFSIZ1024];
68
69volatile sig_atomic_t wantleave = 0;
70volatile sig_atomic_t wantsuspend = 0;
71
72__dead__attribute__((__noreturn__)) void crash(void);
73void display(struct body *, char);
74void leave(int);
75void life(void);
76void newpos(struct body *);
77struct body *newlink(void);
78int process(int);
79void prize(void);
80int rnd(int);
81void setup(void);
82void suspend(int);
83
84int
85main(int argc, char **argv)
86{
87 int retval;
88 struct pollfd pfd[1];
89 const char *errstr;
90 struct timespec t, tn, tdiff;
91
92 timespecclear(&t)(&t)->tv_sec = (&t)->tv_nsec = 0;
93
94 setvbuf(stdout(&__sF[1]), outbuf, _IOFBF0, sizeof outbuf);
95 signal(SIGINT2, leave);
96 signal(SIGQUIT3, leave);
97 signal(SIGTSTP18, suspend); /* process control signal */
98 initscr();
99
100 if (pledge("stdio tty", NULL((void *)0)) == -1)
1
Assuming the condition is false
2
Taking false branch
101 err(1, "pledge");
102
103 cbreak();
104 noecho();
105 keypad(stdscr, TRUE1);
106 slow = (baudrate() <= 1200);
3
Assuming the condition is false
107 clear()wclear(stdscr);
108 if (COLS < 18 || LINES < 5) {
4
Assuming 'COLS' is >= 18
5
Assuming 'LINES' is >= 5
6
Taking false branch
109 endwin();
110 errx(1, "screen too small");
111 }
112 growthscale = COLS * LINES / 2000;
113 if (growthscale == 0)
7
Assuming 'growthscale' is not equal to 0
8
Taking false branch
114 growthscale = 1;
115 if (argc >= 2) {
9
Assuming 'argc' is < 2
10
Taking false branch
116 start_len = strtonum(argv[1], 1, ((LINES-3) * (COLS-2)) / 3,
117 &errstr);
118 if (errstr) {
119 endwin();
120 errx(1, "length argument is %s.", errstr);
121 }
122 }
123 stw = newwin(1, COLS-1, 0, 0);
124 tv = newwin(LINES-1, COLS-1, 1, 0);
125 box(tv, '*', '*')wborder(tv, '*', '*', '*', '*', 0, 0, 0, 0);
126 scrollok(tv, FALSE0);
127 scrollok(stw, FALSE0);
128 wmove(stw, 0, 0);
129 wprintw(stw, " Worm");
130 refresh()wrefresh(stdscr);
131 wrefresh(stw);
132 wrefresh(tv);
133 life(); /* Create the worm */
11
Calling 'life'
134 prize(); /* Put up a goal */
135 wmove(tv, head->y, head->x); /* Leave cursor on worm */
136 wrefresh(tv);
137 while (1) {
138 if (wantleave) {
139 endwin();
140 return 0;
141 }
142 if (wantsuspend) {
143 move(LINES-1, 0)wmove(stdscr,LINES-1,0);
144 refresh()wrefresh(stdscr);
145 endwin();
146 fflush(stdout(&__sF[1]));
147 kill(getpid(), SIGSTOP17);
148 signal(SIGTSTP18, suspend);
149 cbreak();
150 noecho();
151 setup();
152 wantsuspend = 0;
153 }
154
155 if (running) {
156 running--;
157 process(lastch);
158 } else {
159 /* Check for timeout. */
160 clock_gettime(CLOCK_MONOTONIC3, &tn);
161 if (timespeccmp(&t, &tn, <=)(((&t)->tv_sec == (&tn)->tv_sec) ? ((&t)->
tv_nsec <= (&tn)->tv_nsec) : ((&t)->tv_sec <=
(&tn)->tv_sec))
) {
162 t = tn;
163 t.tv_sec += 1;
164
165 process(lastch);
166 continue;
167 }
168
169 /* Prepare next read */
170 pfd[0].fd = STDIN_FILENO0;
171 pfd[0].events = POLLIN0x0001;
172 timespecsub(&t, &tn, &tdiff)do { (&tdiff)->tv_sec = (&t)->tv_sec - (&tn
)->tv_sec; (&tdiff)->tv_nsec = (&t)->tv_nsec
- (&tn)->tv_nsec; if ((&tdiff)->tv_nsec < 0
) { (&tdiff)->tv_sec--; (&tdiff)->tv_nsec += 1000000000L
; } } while (0)
;
173 retval = ppoll(pfd, 1, &tdiff, NULL((void *)0));
174
175 /* Nothing to do if timed out or signal. */
176 if (retval <= 0)
177 continue;
178
179 /* Only update timer if valid key was pressed. */
180 if (process(getch()wgetch(stdscr)) == 0)
181 continue;
182
183 /* Update using clock_gettime(), tn is too old now. */
184 clock_gettime(CLOCK_MONOTONIC3, &t);
185 t.tv_sec += 1;
186 }
187 }
188}
189
190void
191life(void)
192{
193 struct body *bp, *np;
12
'np' declared without an initial value
194 int i,j = 1;
195
196 head = newlink();
197 head->x = start_len % (COLS-5) + 2;
198 head->y = LINES / 2;
199 head->next = NULL((void *)0);
200 display(head, HEAD'@');
201 for (i = 0, bp = head; i < start_len; i++, bp = np) {
13
Assuming 'i' is >= 'start_len'
14
Loop condition is false. Execution continues on line 215
202 np = newlink();
203 np->next = bp;
204 bp->prev = np;
205 if (((bp->x <= 2) && (j == 1)) || ((bp->x >= COLS-4) && (j == -1))) {
206 j *= -1;
207 np->x = bp->x;
208 np->y = bp->y + 1;
209 } else {
210 np->x = bp->x - j;
211 np->y = bp->y;
212 }
213 display(np, BODY'o');
214 }
215 tail = np;
15
Assigned value is garbage or undefined
216 tail->prev = NULL((void *)0);
217 visible_len = start_len + 1;
218}
219
220void
221display(struct body *pos, char chr)
222{
223 wmove(tv, pos->y, pos->x);
224 waddch(tv, chr);
225}
226
227void
228leave(int dummy)
229{
230 wantleave = 1;
231}
232
233int
234rnd(int range)
235{
236 return arc4random_uniform(range);
237}
238
239void
240newpos(struct body *bp)
241{
242 if (visible_len == (LINES-3) * (COLS-3) - 1) {
243 endwin();
244 printf("\nYou won!\nYour final score was %d\n\n", score);
245 exit(0);
246 }
247 do {
248 bp->y = rnd(LINES-3)+ 1;
249 bp->x = rnd(COLS-3) + 1;
250 wmove(tv, bp->y, bp->x);
251 } while(winch(tv) != ' ');
252}
253
254void
255prize(void)
256{
257 int value;
258
259 value = rnd(9) + 1;
260 newpos(&goody);
261 waddch(tv, value+'0');
262 wrefresh(tv);
263}
264
265int
266process(int ch)
267{
268 int x,y;
269 struct body *nh;
270
271 x = head->x;
272 y = head->y;
273 switch(ch) {
274#ifdef KEY_LEFT0404
275 case KEY_LEFT0404:
276#endif
277 case 'h':
278 x--;
279 break;
280#ifdef KEY_DOWN0402
281 case KEY_DOWN0402:
282#endif
283 case 'j':
284 y++;
285 break;
286#ifdef KEY_UP0403
287 case KEY_UP0403:
288#endif
289 case 'k':
290 y--;
291 break;
292#ifdef KEY_RIGHT0405
293 case KEY_RIGHT0405:
294#endif
295 case 'l':
296 x++;
297 break;
298 case 'H':
299 x--;
300 running = RUNLEN8;
301 ch = tolower(ch);
302 break;
303 case 'J':
304 y++;
305 running = RUNLEN8/2;
306 ch = tolower(ch);
307 break;
308 case 'K':
309 y--;
310 running = RUNLEN8/2;
311 ch = tolower(ch);
312 break;
313 case 'L':
314 x++;
315 running = RUNLEN8;
316 ch = tolower(ch);
317 break;
318 case '\f':
319 setup();
320 return (0);
321 case CNTRL('Z')('Z'-'A'+1):
322 suspend(0);
323 return (0);
324 case CNTRL('C')('C'-'A'+1):
325 crash();
326 return (0);
327 case CNTRL('D')('D'-'A'+1):
328 crash();
329 return (0);
330 case ERR(-1):
331 leave(0);
332 return (0);
333 default:
334 return (0);
335 }
336 lastch = ch;
337 if (growing == 0) {
338 display(tail, ' ');
339 tail->next->prev = NULL((void *)0);
340 nh = tail->next;
341 free(tail);
342 tail = nh;
343 visible_len--;
344 } else
345 growing--;
346 display(head, BODY'o');
347 wmove(tv, y, x);
348 if (isdigit(ch = winch(tv))) {
349 int amt = ch - '0';
350 growing += amt * growthscale;
351 prize();
352 score += amt;
353 running = 0;
354 wmove(stw, 0, COLS - 12);
355 wprintw(stw, "Score: %3d", score);
356 wrefresh(stw);
357 } else if(ch != ' ')
358 crash();
359 nh = newlink();
360 nh->next = NULL((void *)0);
361 nh->prev = head;
362 head->next = nh;
363 nh->y = y;
364 nh->x = x;
365 display(nh, HEAD'@');
366 head = nh;
367 visible_len++;
368 if (!(slow && running)) {
369 wmove(tv, head->y, head->x);
370 wrefresh(tv);
371 }
372 return (1);
373}
374
375struct body *
376newlink(void)
377{
378 struct body *tmp;
379
380 if ((tmp = malloc(sizeof (struct body))) == NULL((void *)0)) {
381 endwin();
382 errx(1, "out of memory");
383 }
384 return (tmp);
385}
386
387void
388crash(void)
389{
390 sleep(2);
391 clear()wclear(stdscr);
392 endwin();
393 printf("Well, you ran into something and the game is over.\n");
394 printf("Your final score was %d\n", score);
395 exit(0); /* leave() calls endwin(), which would hose the printf()'s */
396}
397
398void
399suspend(int dummy)
400{
401 wantsuspend = 1;
402}
403
404void
405setup(void)
406{
407 clear()wclear(stdscr);
408 refresh()wrefresh(stdscr);
409 touchwin(stw)wtouchln((stw), 0, ((stw) ? ((stw)->_maxy + 1) : (-1)), 1);
410 wrefresh(stw);
411 touchwin(tv)wtouchln((tv), 0, ((tv) ? ((tv)->_maxy + 1) : (-1)), 1);
412 wrefresh(tv);
413}