Bug Summary

File:pong.c
Warning:line 42, column 18
The right operand of '!=' is a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name pong.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 2 -pic-is-pie -mthread-model posix -mframe-pointer=all -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -fno-plt -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib/clang/10.0.0 -include /home/buildbot/lwan-worker/clang-analyze/build/lwan-build-config.h -D _FILE_OFFSET_BITS=64 -D _TIME_BITS=64 -I /home/buildbot/lwan-worker/clang-analyze/build/src/lib/missing -I /usr/include/luajit-2.0 -I /usr/include/valgrind -I /home/buildbot/lwan-worker/clang-analyze/build/src/lib -internal-isystem /usr/local/include -internal-isystem /usr/lib/clang/10.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-unused-parameter -Wno-free-nonheap-object -std=gnu99 -fdebug-compilation-dir /home/buildbot/lwan-worker/clang-analyze/build/src/samples/clock -ferror-limit 19 -fmessage-length 0 -stack-protector 2 -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -analyzer-output=html -faddrsig -o /home/buildbot/lwan-worker/clang-analyze/CLANG/2020-07-04-211314-1084088-1 -x c /home/buildbot/lwan-worker/clang-analyze/build/src/samples/clock/pong.c
1/*
2 * C port of Daniel Esteban's Pong Clock for Lwan
3 * Copyright (C) 2019 Daniel Esteban <conejo@conejo.me>
4 * Copyright (C) 2020 Leandro A. F. Pereira <leandro@hardinfo.org>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 */
24
25#include <limits.h>
26#include <stdlib.h>
27#include <math.h>
28
29#include "pong.h"
30
31extern const uint8_t digital_clock_font[10][5];
32
33static float rand_float(float scale)
34{
35 return ((float)rand() / (float)(RAND_MAX2147483647)) * scale;
36}
37
38static void pong_time_update(struct pong_time *pong_time)
39{
40 time_t cur_time = time(NULL((void*)0));
41
42 if (cur_time != pong_time->last_time) {
23
The right operand of '!=' is a garbage value
43 char digits[5];
44
45 strftime(digits, sizeof(digits), "%H%M", localtime(&cur_time));
46
47 for (int i = 0; i < 4; i++)
48 pong_time->time[i] = digits[i] - '0';
49
50 pong_time->hour = (digits[0] - '0') * 10 + digits[1] - '0';
51 pong_time->minute = (digits[2] - '0') * 10 + digits[3] - '0';
52
53 pong_time->last_time = cur_time;
54 }
55}
56
57void pong_init(struct pong *pong, ge_GIF *gif)
58{
59 float ball_y = rand_float(16.0f) + 8.0f;
60
61 *pong = (struct pong){
62 .gif = gif,
63 .ball_x = {.pos = 31.0f, .vel = 1.0f},
64 .ball_y = {.pos = ball_y, .vel = rand() % 2 ? -0.5f : 0.5f},
65 .player_left = {.y = 8, .target_y = ball_y},
66 .player_right = {.y = 18, .target_y = ball_y},
67 .player_loss = 0,
68 .game_stopped = 0,
69 };
70
71 pong_time_update(&pong->time);
72}
73
74static void draw_pixel(unsigned char *frame, int x, int y, unsigned char color)
75{
76 if (x < 64 && y < 32)
77 frame[y * 64 + x] = color;
78}
79
80static void pong_draw_net(const struct pong *pong)
81{
82 for (int i = 1; i < 32; i += 2)
83 draw_pixel(pong->gif->frame, 31, i, 6);
84}
85
86static void pong_draw_player(const struct pong *pong, int x, int y)
87{
88 for (int i = 0; i < 2; i++) {
89 for (int j = 0; j < 8; j++)
90 draw_pixel(pong->gif->frame, x + i, y + j, 3);
91 }
92}
93
94static void pong_draw_ball(const struct pong *pong)
95{
96 int x = (int)pong->ball_x.pos;
97 int y = (int)pong->ball_y.pos;
98
99 draw_pixel(pong->gif->frame, x, y, 1);
100 draw_pixel(pong->gif->frame, x + 1, y, 1);
101 draw_pixel(pong->gif->frame, x, y + 1, 1);
102 draw_pixel(pong->gif->frame, x + 1, y + 1, 1);
103}
104
105static void pong_draw_time(const struct pong *pong)
106{
107 static const uint8_t base_offsets[] = {23, 23, 25, 25};
108 static const uint8_t colors[] = {0, 6};
109 unsigned char *frame = pong->gif->frame;
110
111 for (int digit = 0; digit < 4; digit++) {
112 int dig = pong->time.time[digit];
113 uint8_t off = base_offsets[digit];
114
115 for (int line = 0, base = digit * 4; line < 5; line++, base += 64) {
116 frame[base + 0 + off] = colors[!!(digital_clock_font[dig][line] & 1<<2)];
117 frame[base + 1 + off] = colors[!!(digital_clock_font[dig][line] & 1<<1)];
118 frame[base + 2 + off] = colors[!!(digital_clock_font[dig][line] & 1<<0)];
119 }
120 }
121}
122
123static float pong_calculate_end_point(const struct pong *pong, bool_Bool hit)
124{
125 float x = pong->ball_x.pos;
126 float y = pong->ball_y.pos;
127 float vel_x = pong->ball_x.vel;
128 float vel_y = pong->ball_y.vel;
129
130 for (;;) {
131 x += vel_x;
132 y += vel_y;
133 if (hit) {
134 if (x >= 60.0f || x <= 2.0f)
135 return y;
136 } else {
137 if (x >= 62.0f || x <= 0.0f)
138 return y;
139 }
140 if (y >= 30.0f || y <= 0.0f)
141 vel_y = -vel_y;
142 }
143}
144
145uint64_t pong_draw(struct pong *pong)
146{
147 if (pong->game_stopped < 20) {
1
Assuming field 'game_stopped' is >= 20
2
Taking false branch
148 pong->game_stopped++;
149 } else {
150 pong->ball_x.pos += pong->ball_x.vel;
151 pong->ball_y.pos += pong->ball_y.vel;
152
153 if ((pong->ball_x.pos >= 60.0f && pong->player_loss != 1) ||
3
Assuming the condition is false
154 (pong->ball_x.pos <= 2.0f && pong->player_loss != -1)) {
4
Assuming the condition is false
155 pong->ball_x.vel = -pong->ball_x.vel;
156 if (rand() % 4 > 0) {
157 if (rand() % 2 == 0) {
158 if (pong->ball_y.vel > 0.0f && pong->ball_y.vel < 2.5f)
159 pong->ball_y.vel += 0.2f;
160 else if (pong->ball_y.vel < 0.0f &&
161 pong->ball_y.vel > -2.5f)
162 pong->ball_y.vel -= 0.2f;
163
164 if (pong->ball_x.pos >= 60.0f)
165 pong->player_right.target_y += 1.0f + rand_float(3);
166 else
167 pong->player_left.target_y += 1.0f + rand_float(3);
168 } else {
169 if (pong->ball_y.vel > 0.5f)
170 pong->ball_y.vel -= 0.2f;
171 else if (pong->ball_y.vel < -0.5f)
172 pong->ball_y.vel += 0.2f;
173
174 if (pong->ball_x.pos >= 60.0f)
175 pong->player_right.target_y -= 1.0f + rand_float(3);
176 else
177 pong->player_left.target_y -= 1.0f + rand_float(3);
178 }
179
180 if (pong->player_left.target_y < 0.0f)
181 pong->player_left.target_y = 0.0f;
182 else if (pong->player_left.target_y > 24.0f)
183 pong->player_left.target_y = 24.0f;
184
185 if (pong->player_right.target_y < 0.0f)
186 pong->player_right.target_y = 0.0f;
187 else if (pong->player_right.target_y > 24.0f)
188 pong->player_right.target_y = 24.0f;
189 }
190 } else if ((pong->ball_x.pos > 62.0f && pong->player_loss == 1) ||
5
Assuming the condition is false
191 (pong->ball_x.pos < 0.0f && pong->player_loss == -1)) {
6
Assuming the condition is false
192 pong_init(pong, pong->gif);
193 }
194
195 if (pong->ball_y.pos >= 30.0f || pong->ball_y.pos <= 0.0f)
7
Assuming the condition is false
8
Assuming the condition is false
9
Taking false branch
196 pong->ball_y.vel = -pong->ball_y.vel;
197
198 if (roundf(pong->ball_x.pos) == 40.0f + rand_float(13)) {
10
Assuming the condition is false
11
Taking false branch
199 pong->player_left.target_y = pong->ball_y.pos - 3.0f;
200
201 if (pong->player_left.target_y < 0.0f)
202 pong->player_left.target_y = 0.0f;
203 else if (pong->player_left.target_y > 24.0f)
204 pong->player_left.target_y = 24.0f;
205 }
206 if (roundf(pong->ball_x.pos) == 8 + rand_float(13)) {
12
Assuming the condition is false
13
Taking false branch
207 pong->player_right.target_y = pong->ball_y.pos - 3;
208
209 if (pong->player_right.target_y < 0)
210 pong->player_right.target_y = 0;
211 else if (pong->player_right.target_y > 24)
212 pong->player_right.target_y = 24;
213 }
214
215 if (pong->player_left.target_y > pong->player_left.y)
14
Assuming field 'target_y' is <= field 'y'
15
Taking false branch
216 pong->player_left.y++;
217 else if (pong->player_left.target_y < pong->player_left.y)
16
Assuming field 'target_y' is >= field 'y'
17
Taking false branch
218 pong->player_left.y--;
219
220 if (pong->player_right.target_y > pong->player_right.y)
18
Assuming field 'target_y' is > field 'y'
19
Taking true branch
221 pong->player_right.y++;
222 else if (pong->player_right.target_y < pong->player_right.y)
223 pong->player_right.y--;
224
225 /* If the ball is in the middle, check if we need to lose and calculate
226 * the endpoint to avoid/hit the ball */
227 if (roundf(pong->ball_x.pos) == 32.0f) {
20
Assuming the condition is true
21
Taking true branch
228 struct pong_time cur_time;
229
230 pong_time_update(&cur_time);
22
Calling 'pong_time_update'
231
232 if (cur_time.minute != pong->time.minute && pong->player_loss == 0) {
233 /* Need to change one or the other */
234 if (cur_time.minute == 0) /* Need to change the hour */
235 pong->player_loss = 1;
236 else /* Need to change the minute */
237 pong->player_loss = -1;
238 }
239
240 if (pong->ball_x.vel < 0) { /* Moving to the left */
241 pong->player_left.target_y =
242 pong_calculate_end_point(pong, pong->player_loss != -1) - 3;
243 if (pong->player_loss == -1) { /* We need to lose */
244 if (pong->player_left.target_y < 16)
245 pong->player_left.target_y = 19 + rand_float(5);
246 else
247 pong->player_left.target_y = 5 + rand_float(2);
248 }
249
250 if (pong->player_left.target_y < 0)
251 pong->player_left.target_y = 0;
252 else if (pong->player_left.target_y > 24)
253 pong->player_left.target_y = 24;
254 } else if (pong->ball_x.vel > 0) { /* Moving to the right */
255 pong->player_right.target_y =
256 pong_calculate_end_point(pong, pong->player_loss != 1) - 3;
257 if (pong->player_loss == -1) { /* We need to lose */
258 if (pong->player_right.target_y < 16)
259 pong->player_right.target_y = 19 + rand_float(5);
260 else
261 pong->player_right.target_y = 5 + rand_float(2);
262 }
263
264 if (pong->player_right.target_y < 0)
265 pong->player_right.target_y = 0;
266 else if (pong->player_right.target_y > 24)
267 pong->player_right.target_y = 24;
268 }
269
270 if (pong->ball_y.pos < 0)
271 pong->ball_y.pos = 0;
272 else if (pong->ball_y.pos > 30)
273 pong->ball_y.pos = 30;
274 }
275 }
276
277 memset(pong->gif->frame, 0, 64 * 32);
278 pong_draw_net(pong);
279 pong_draw_time(pong);
280 pong_draw_player(pong, 0, pong->player_left.y);
281 pong_draw_player(pong, 62, pong->player_right.y);
282 pong_draw_ball(pong);
283
284 return 8;
285}