Bug Summary

File:src/games/gomoku/main.c
Warning:line 191, column 30
The left operand of '==' is a garbage value

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 main.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/games/gomoku/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/games/gomoku/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/games/gomoku/main.c
1/* $OpenBSD: main.c,v 1.33 2021/10/23 11:22:48 mestre Exp $ */
2/*
3 * Copyright (c) 1994
4 * The Regents of the University of California. All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * Ralph Campbell.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include <curses.h>
35#include <err.h>
36#include <limits.h>
37#include <signal.h>
38#include <stdlib.h>
39#include <string.h>
40#include <unistd.h>
41
42#include "gomoku.h"
43
44#define USER0 0 /* get input from standard input */
45#define PROGRAM1 1 /* get input from program */
46#define INPUTF2 2 /* get input from a file */
47
48extern char *__progname; /* name of program */
49
50int interactive = 1; /* true if interactive */
51int debug; /* true if debugging */
52int test; /* both moves come from 1: input, 2: computer */
53FILE *debugfp; /* file for debug output */
54FILE *inputfp; /* file for debug input */
55
56char pdir[4] = "-\\|/";
57char fmtbuf[128];
58
59struct spotstr board[BAREA((19 +2)*(19 +1)+1)]; /* info for board */
60struct combostr frames[FAREA(19*(19 -4) + (19 -4)*(19 -4) + 19*(19 -4) + (19 -4)*(19 -4))]; /* storage for all frames */
61struct combostr *sortframes[2]; /* sorted list of non-empty frames */
62u_char overlap[FAREA(19*(19 -4) + (19 -4)*(19 -4) + 19*(19 -4) + (19 -4)*(19 -4)) * FAREA(19*(19 -4) + (19 -4)*(19 -4) + 19*(19 -4) + (19 -4)*(19 -4))]; /* true if frame [a][b] overlap */
63short intersect[FAREA(19*(19 -4) + (19 -4)*(19 -4) + 19*(19 -4) + (19 -4)*(19 -4)) * FAREA(19*(19 -4) + (19 -4)*(19 -4) + 19*(19 -4) + (19 -4)*(19 -4))]; /* frame [a][b] intersection */
64int movelog[BSZ19 * BSZ19]; /* log of all the moves */
65int movenum; /* current move number */
66char *plyr[2]; /* who's who */
67
68static char you[LOGIN_NAME_MAX32]; /* username */
69
70int
71main(int argc, char **argv)
72{
73 char buf[128];
74 char fname[PATH_MAX1024];
75 int color = BLACK0, curmove = 0, i, ch;
76 int input[2];
77 static char *fmt[2] = {
78 "%3d %-6s",
79 "%3d %-6s"
80 };
81 char *tmpname;
82
83 if ((tmpname = getlogin()) != NULL((void *)0))
1
Assuming the condition is false
2
Taking false branch
84 strlcpy(you, tmpname, sizeof(you));
85 else
86 strlcpy(you, "you", sizeof(you));
87
88 while ((ch = getopt(argc, argv, "bcdD:hu")) != -1) {
3
Assuming the condition is false
4
Loop condition is false. Execution continues on line 114
89 switch (ch) {
90 case 'b': /* background */
91 interactive = 0;
92 break;
93 case 'd': /* debugging */
94 debug++;
95 break;
96 case 'D': /* log debug output to file */
97 if ((debugfp = fopen(optarg, "w")) == NULL((void *)0))
98 err(1, "%s", optarg);
99 break;
100 case 'u': /* testing: user versus user */
101 test = 1;
102 break;
103 case 'c': /* testing: computer versus computer */
104 test = 2;
105 break;
106 case 'h':
107 default:
108 fprintf(stderr(&__sF[2]),
109 "usage: %s [-bcdu] [-D debugfile] [inputfile]\n",
110 __progname);
111 return 1;
112 }
113 }
114 argc -= optind;
115 argv += optind;
116 if (argc) {
5
Assuming 'argc' is 0
6
Taking false branch
117 if ((inputfp = fopen(*argv, "r")) == NULL((void *)0))
118 err(1, "%s", *argv);
119 }
120
121 if (interactive
6.1
'interactive' is 1
)
7
Taking true branch
122 cursinit(); /* initialize curses */
123
124 if (pledge("stdio rpath wpath cpath tty", NULL((void *)0)) == -1)
8
Assuming the condition is false
9
Taking false branch
125 err(1, "pledge");
126
127again:
128 bdinit(board); /* initialize board contents */
129
130 if (interactive
9.1
'interactive' is 1
) {
10
Taking true branch
131 plyr[BLACK0] = plyr[WHITE1] = "???";
132 bdisp_init(); /* initialize display of board */
133#ifdef DEBUG
134 signal(SIGINT2, whatsup);
135#else
136 signal(SIGINT2, quit);
137#endif
138
139 if (inputfp == NULL((void *)0) && test == 0) {
11
Assuming 'inputfp' is equal to NULL
12
Assuming 'test' is not equal to 0
13
Taking false branch
140 ask("black or white? ");
141 while (((ch = getchar()(!__isthreaded ? (--((&__sF[0]))->_r < 0 ? __srget(
(&__sF[0])) : (int)(*((&__sF[0]))->_p++)) : (getc)
((&__sF[0])))
) != 'b') && (ch != 'B') &&
142 (ch != 'w') && (ch != 'W')) {
143 move(BSZ3, 0)wmove(stdscr,((19 +3)),(0));
144 printw("Black moves first. Please enter `black' or `white'\n");
145 refresh()wrefresh(stdscr);
146 }
147 if (ch == 'b' || ch == 'B')
148 color = BLACK0;
149 else
150 color = WHITE1;
151 move(BSZ3, 0)wmove(stdscr,((19 +3)),(0));
152 clrtoeol()wclrtoeol(stdscr);
153 }
154 } else {
155 setvbuf(stdout(&__sF[1]), NULL((void *)0), _IONBF2, 0);
156 get_line(buf, sizeof(buf));
157 if (strcmp(buf, "black") == 0)
158 color = BLACK0;
159 else if (strcmp(buf, "white") == 0)
160 color = WHITE1;
161 else {
162 snprintf(fmtbuf, sizeof fmtbuf,
163 "Huh? Expected `black' or `white', got `%s'\n",
164 buf);
165 panic(fmtbuf);
166 }
167 }
168
169 if (inputfp
13.1
'inputfp' is null
) {
14
Taking false branch
170 input[BLACK0] = INPUTF2;
171 input[WHITE1] = INPUTF2;
172 } else {
173 switch (test) {
174 case 0: /* user versus program */
175 input[color] = USER0;
176 input[!color] = PROGRAM1;
177 break;
178
179 case 1: /* user versus user */
180 input[BLACK0] = USER0;
181 input[WHITE1] = USER0;
182 break;
183
184 case 2: /* program versus program */
185 input[BLACK0] = PROGRAM1;
186 input[WHITE1] = PROGRAM1;
187 break;
188 }
189 }
190 if (interactive
15.1
'interactive' is 1
) {
15
'Default' branch taken. Execution continues on line 190
191 plyr[BLACK0] = input[BLACK0] == USER0 ? you : __progname;
16
Taking true branch
17
The left operand of '==' is a garbage value
192 plyr[WHITE1] = input[WHITE1] == USER0 ? you : __progname;
193 bdwho(1);
194 }
195
196 for (color = BLACK0; ; color = !color) {
197 top:
198 switch (input[color]) {
199 case INPUTF2: /* input comes from a file */
200 curmove = readinput(inputfp);
201 if (curmove != ILLEGAL2)
202 break;
203 switch (test) {
204 case 0: /* user versus program */
205 input[color] = USER0;
206 input[!color] = PROGRAM1;
207 break;
208
209 case 1: /* user versus user */
210 input[BLACK0] = USER0;
211 input[WHITE1] = USER0;
212 break;
213
214 case 2: /* program versus program */
215 input[BLACK0] = PROGRAM1;
216 input[WHITE1] = PROGRAM1;
217 break;
218 }
219 plyr[BLACK0] = input[BLACK0] == USER0 ? you : __progname;
220 plyr[WHITE1] = input[WHITE1] == USER0 ? you : __progname;
221 bdwho(1);
222 goto top;
223
224 case USER0: /* input comes from standard input */
225 getinput:
226 if (interactive) {
227 ask("Enter move (hjklyubn/S/Q)");
228 curmove = getcoord();
229 if (curmove == SAVE5) {
230 FILE *fp;
231
232 ask("save file name? ");
233 (void)get_line(fname, sizeof(fname));
234 if ((fp = fopen(fname, "w")) == NULL((void *)0)) {
235 logit("cannot create save file");
236 goto getinput;
237 }
238 for (i = 0; i < movenum - 1; i++)
239 fprintf(fp, "%s\n",
240 stoc(movelog[i]));
241 fclose(fp);
242 goto getinput;
243 }
244 if (curmove != RESIGN1 &&
245 board[curmove].s_occ != EMPTY2) {
246 /* logit("Illegal move"); */
247 beep();
248 goto getinput;
249 }
250 } else {
251 if (!get_line(buf, sizeof(buf))) {
252 curmove = RESIGN1;
253 break;
254 }
255 if (buf[0] == '\0')
256 goto getinput;
257 curmove = ctos(buf);
258 }
259 break;
260
261 case PROGRAM1: /* input comes from the program */
262 if (interactive)
263 ask("Thinking...");
264 curmove = pickmove(color);
265 break;
266 }
267 if (interactive) {
268 snprintf(fmtbuf, sizeof fmtbuf,
269 fmt[color], movenum, stoc(curmove));
270 logit(fmtbuf);
271 }
272 if ((i = makemove(color, curmove)) != MOVEOK0)
273 break;
274 if (interactive)
275 bdisp();
276 }
277 if (interactive) {
278 move(BSZ3, 0)wmove(stdscr,((19 +3)),(0));
279 switch (i) {
280 case WIN3:
281 if (input[color] == PROGRAM1)
282 addstr("Ha ha, I won")waddnstr(stdscr,("Ha ha, I won"),-1);
283 else
284 if (input[0] == USER0 && input[1] == USER0)
285 addstr("Well, you won (and lost).")waddnstr(stdscr,("Well, you won (and lost)."),-1);
286 else
287 addstr("Rats! You won")waddnstr(stdscr,("Rats! You won"),-1);
288 break;
289 case TIE4:
290 addstr("Wow! its a tie")waddnstr(stdscr,("Wow! its a tie"),-1);
291 break;
292 case ILLEGAL2:
293 addstr("Illegal move")waddnstr(stdscr,("Illegal move"),-1);
294 break;
295 }
296 clrtoeol()wclrtoeol(stdscr);
297 bdisp();
298 if (i != RESIGN1) {
299 replay:
300 ask("replay? ");
301 if (get_line(buf, sizeof(buf)) &&
302 (buf[0] == 'y' || buf[0] == 'Y'))
303 goto again;
304 if (strcmp(buf, "save") == 0) {
305 FILE *fp;
306
307 ask("save file name? ");
308 (void)get_line(buf, sizeof(buf));
309 if ((fp = fopen(buf, "w")) == NULL((void *)0)) {
310 logit("cannot create save file");
311 goto replay;
312 }
313 for (i = 0; i < movenum - 1; i++)
314 fprintf(fp, "%s\n",
315 stoc(movelog[i]));
316 fclose(fp);
317 goto replay;
318 }
319 }
320 }
321 quit(0);
322}
323
324int
325readinput(FILE *fp)
326{
327 char *cp;
328 int c;
329
330 cp = fmtbuf;
331 while ((c = getc(fp)(!__isthreaded ? (--(fp)->_r < 0 ? __srget(fp) : (int)(
*(fp)->_p++)) : (getc)(fp))
) != EOF(-1) && c != '\n')
332 *cp++ = c;
333 *cp = '\0';
334 return (ctos(fmtbuf));
335}
336
337#ifdef DEBUG
338/*
339 * Handle strange situations.
340 */
341void
342whatsup(int signum)
343{
344 int i, pnum, n, s1, s2, d1, d2;
345 struct spotstr *sp;
346 FILE *fp;
347 char *str;
348 struct elist *ep;
349 struct combostr *cbp;
350
351 if (!interactive)
352 quit(0);
353top:
354 ask("cmd? ");
355 if (!get_line(fmtbuf, sizeof(fmtbuf)))
356 quit(0);
357 switch (*fmtbuf) {
358 case '\0':
359 goto top;
360 case 'q': /* conservative quit */
361 quit(0);
362 case 'd': /* set debug level */
363 debug = fmtbuf[1] - '0';
364 snprintf(fmtbuf, sizeof fmtbuf,
365 "Debug set to %d", debug);
366 dlog(fmtbuf);
367 sleep(1);
368 case 'c':
369 break;
370 case 'b': /* back up a move */
371 if (movenum > 1) {
372 movenum--;
373 board[movelog[movenum - 1]].s_occ = EMPTY2;
374 bdisp();
375 }
376 goto top;
377 case 's': /* suggest a move */
378 i = fmtbuf[1] == 'b' ? BLACK0 : WHITE1;
379 snprintf(fmtbuf, sizeof fmtbuf,
380 "suggest %c %s", i == BLACK0 ? 'B' : 'W',
381 stoc(pickmove(i)));
382 dlog(fmtbuf);
383 goto top;
384 case 'f': /* go forward a move */
385 board[movelog[movenum - 1]].s_occ = movenum & 1 ? BLACK0 : WHITE1;
386 movenum++;
387 bdisp();
388 goto top;
389 case 'l': /* print move history */
390 if (fmtbuf[1] == '\0') {
391 for (i = 0; i < movenum - 1; i++)
392 dlog(stoc(movelog[i]));
393 goto top;
394 }
395 if ((fp = fopen(fmtbuf + 1, "w")) == NULL((void *)0))
396 goto top;
397 for (i = 0; i < movenum - 1; i++) {
398 fprintf(fp, "%s", stoc(movelog[i]));
399 if (++i < movenum - 1)
400 fprintf(fp, " %s\n", stoc(movelog[i]));
401 else
402 fputc('\n', fp);
403 }
404 bdump(fp);
405 fclose(fp);
406 goto top;
407 case 'o':
408 n = 0;
409 for (str = fmtbuf + 1; *str; str++)
410 if (*str == ',') {
411 for (d1 = 0; d1 < 4; d1++)
412 if (str[-1] == pdir[d1])
413 break;
414 str[-1] = '\0';
415 sp = &board[s1 = ctos(fmtbuf + 1)];
416 n = (sp->s_frame[d1] - frames) * FAREA(19*(19 -4) + (19 -4)*(19 -4) + 19*(19 -4) + (19 -4)*(19 -4));
417 *str++ = '\0';
418 break;
419 }
420 sp = &board[s2 = ctos(str)];
421 while (*str)
422 str++;
423 for (d2 = 0; d2 < 4; d2++)
424 if (str[-1] == pdir[d2])
425 break;
426 n += sp->s_frame[d2] - frames;
427 str = fmtbuf;
428 snprintf(str, fmtbuf + sizeof fmtbuf - str,
429 "overlap %s%c,", stoc(s1), pdir[d1]);
430 str += strlen(str);
431 snprintf(str, fmtbuf + sizeof fmtbuf - str,
432 "%s%c = %x", stoc(s2), pdir[d2], overlap[n]);
433 dlog(fmtbuf);
434 goto top;
435 case 'p':
436 sp = &board[i = ctos(fmtbuf + 1)];
437 snprintf(fmtbuf, sizeof fmtbuf,
438 "V %s %x/%d %d %x/%d %d %d %x", stoc(i),
439 sp->s_combo[BLACK0].s, sp->s_level[BLACK0],
440 sp->s_nforce[BLACK0],
441 sp->s_combo[WHITE1].s, sp->s_level[WHITE1],
442 sp->s_nforce[WHITE1], sp->s_wval, sp->s_flg);
443 dlog(fmtbuf);
444 snprintf(fmtbuf, sizeof fmtbuf,
445 "FB %s %x %x %x %x", stoc(i),
446 sp->s_fval[BLACK0][0].s, sp->s_fval[BLACK0][1].s,
447 sp->s_fval[BLACK0][2].s, sp->s_fval[BLACK0][3].s);
448 dlog(fmtbuf);
449 snprintf(fmtbuf, sizeof fmtbuf,
450 "FW %s %x %x %x %x", stoc(i),
451 sp->s_fval[WHITE1][0].s, sp->s_fval[WHITE1][1].s,
452 sp->s_fval[WHITE1][2].s, sp->s_fval[WHITE1][3].s);
453 dlog(fmtbuf);
454 goto top;
455 case 'e': /* e {b|w} [0-9] spot */
456 str = fmtbuf + 1;
457 if (*str >= '0' && *str <= '9')
458 n = *str++ - '0';
459 else
460 n = 0;
461 sp = &board[i = ctos(str)];
462 for (ep = sp->s_empty; ep; ep = ep->e_next) {
463 cbp = ep->e_combo;
464 if (n) {
465 if (cbp->c_nframes > n)
466 continue;
467 if (cbp->c_nframes != n)
468 break;
469 }
470 printcombo(cbp, fmtbuf, sizeof fmtbuf);
471 dlog(fmtbuf);
472 }
473 goto top;
474 default:
475syntax:
476 dlog("Options are:");
477 dlog("q - quit");
478 dlog("c - continue");
479 dlog("d# - set debug level to #");
480 dlog("p# - print values at #");
481 goto top;
482 }
483}
484#endif /* DEBUG */
485
486/*
487 * Display debug info.
488 */
489void
490dlog(char *str)
491{
492
493 if (debugfp)
494 fprintf(debugfp, "%s\n", str);
495 if (interactive)
496 dislog(str);
497 else
498 fprintf(stderr(&__sF[2]), "%s\n", str);
499}
500
501void
502logit(char *str)
503{
504
505 if (debugfp)
506 fprintf(debugfp, "%s\n", str);
507 if (interactive)
508 dislog(str);
509 else
510 printf("%s\n", str);
511}
512
513/*
514 * Deal with a fatal error.
515 */
516void
517qlog(char *str)
518{
519 dlog(str);
520 if (interactive)
521 beep();
522 sleep(5);
523 quit(0);
524}
525
526void
527quit(int sig)
528{
529 if (interactive) {
530 bdisp(); /* show final board */
531 cursfini();
532 }
533 exit(0);
534}
535
536/*
537 * Die gracefully.
538 */
539void
540panic(char *str)
541{
542 fprintf(stderr(&__sF[2]), "%s: %s\n", __progname, str);
543 fputs("resign\n", stdout(&__sF[1]));
544 quit(0);
545}