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-211348-1085029-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 <math.h>
27#include <stdlib.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 = pong_time->time[0] * 10 + pong_time->time[1];
51 pong_time->minute = pong_time->time[2] * 10 + pong_time->time[3];
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
145static void pong_clamp_player_pos(struct pong *pong, bool_Bool left, bool_Bool right)
146{
147 if (left) {
148 if (pong->player_left.target_y < 0.0f)
149 pong->player_left.target_y = 0.0f;
150 else if (pong->player_left.target_y > 24.0f)
151 pong->player_left.target_y = 24.0f;
152 }
153
154 if (right) {
155 if (pong->player_right.target_y < 0.0f)
156 pong->player_right.target_y = 0.0f;
157 else if (pong->player_right.target_y > 24.0f)
158 pong->player_right.target_y = 24.0f;
159 }
160}
161
162uint64_t pong_draw(struct pong *pong)
163{
164 if (pong->game_stopped < 20) {
1
Assuming field 'game_stopped' is >= 20
2
Taking false branch
165 pong->game_stopped++;
166 goto draw;
167 }
168
169 pong->ball_x.pos += pong->ball_x.vel;
170 pong->ball_y.pos += pong->ball_y.vel;
171
172 if ((pong->ball_x.pos >= 60.0f && pong->player_loss != 1) ||
3
Assuming the condition is false
173 (pong->ball_x.pos <= 2.0f && pong->player_loss != -1)) {
4
Assuming the condition is false
174 pong->ball_x.vel = -pong->ball_x.vel;
175 if (rand() % 4 > 0) {
176 if (rand() % 2 == 0) {
177 if (pong->ball_y.vel > 0.0f && pong->ball_y.vel < 2.5f)
178 pong->ball_y.vel += 0.2f;
179 else if (pong->ball_y.vel < 0.0f && pong->ball_y.vel > -2.5f)
180 pong->ball_y.vel -= 0.2f;
181
182 if (pong->ball_x.pos >= 60.0f)
183 pong->player_right.target_y += 1.0f + rand_float(3);
184 else
185 pong->player_left.target_y += 1.0f + rand_float(3);
186 } else {
187 if (pong->ball_y.vel > 0.5f)
188 pong->ball_y.vel -= 0.2f;
189 else if (pong->ball_y.vel < -0.5f)
190 pong->ball_y.vel += 0.2f;
191
192 if (pong->ball_x.pos >= 60.0f)
193 pong->player_right.target_y -= 1.0f + rand_float(3);
194 else
195 pong->player_left.target_y -= 1.0f + rand_float(3);
196 }
197
198 pong_clamp_player_pos(pong, true1, true1);
199 }
200 } else if ((pong->ball_x.pos > 62.0f && pong->player_loss == 1) ||
5
Assuming the condition is false
201 (pong->ball_x.pos < 0.0f && pong->player_loss == -1)) {
6
Assuming the condition is false
202 pong_init(pong, pong->gif);
203 }
204
205 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
206 pong->ball_y.vel = -pong->ball_y.vel;
207
208 if (roundf(pong->ball_x.pos) == 40.0f + rand_float(13)) {
10
Assuming the condition is false
11
Taking false branch
209 pong->player_left.target_y = pong->ball_y.pos - 3.0f;
210 pong_clamp_player_pos(pong, true1, false0);
211 } else if (roundf(pong->ball_x.pos) == 8 + rand_float(13)) {
12
Assuming the condition is false
13
Taking false branch
212 pong->player_right.target_y = pong->ball_y.pos - 3.0f;
213 pong_clamp_player_pos(pong, false0, true1);
214 }
215
216 if (pong->player_left.target_y > pong->player_left.y)
14
Assuming field 'target_y' is <= field 'y'
15
Taking false branch
217 pong->player_left.y++;
218 else if (pong->player_left.target_y < pong->player_left.y)
16
Assuming field 'target_y' is >= field 'y'
17
Taking false branch
219 pong->player_left.y--;
220
221 if (pong->player_right.target_y > pong->player_right.y)
18
Assuming field 'target_y' is > field 'y'
19
Taking true branch
222 pong->player_right.y++;
223 else if (pong->player_right.target_y < pong->player_right.y)
224 pong->player_right.y--;
225
226 /* If the ball is in the middle, check if we need to lose and calculate
227 * the endpoint to avoid/hit the ball */
228 if (roundf(pong->ball_x.pos) == 32.0f) {
20
Assuming the condition is true
21
Taking true branch
229 struct pong_time cur_time;
230
231 pong_time_update(&cur_time);
22
Calling 'pong_time_update'
232
233 if (cur_time.minute != pong->time.minute && pong->player_loss == 0) {
234 /* Need to change one or the other */
235 if (cur_time.minute == 0) /* Need to change the hour */
236 pong->player_loss = 1;
237 else /* Need to change the minute */
238 pong->player_loss = -1;
239 }
240
241 if (pong->ball_x.vel < 0) { /* Moving to the left */
242 pong->player_left.target_y =
243 pong_calculate_end_point(pong, pong->player_loss != -1) - 3;
244 if (pong->player_loss == -1) { /* We need to lose */
245 if (pong->player_left.target_y < 16)
246 pong->player_left.target_y = 19 + rand_float(5);
247 else
248 pong->player_left.target_y = 5 + rand_float(2);
249 }
250
251 pong_clamp_player_pos(pong, true1, false0);
252 } else if (pong->ball_x.vel > 0) { /* Moving to the right */
253 pong->player_right.target_y =
254 pong_calculate_end_point(pong, pong->player_loss != 1) - 3;
255 if (pong->player_loss == -1) { /* We need to lose */
256 if (pong->player_right.target_y < 16)
257 pong->player_right.target_y = 19 + rand_float(5);
258 else
259 pong->player_right.target_y = 5 + rand_float(2);
260 }
261
262 pong_clamp_player_pos(pong, false0, true1);
263 }
264
265 if (pong->ball_y.pos < 0)
266 pong->ball_y.pos = 0;
267 else if (pong->ball_y.pos > 30)
268 pong->ball_y.pos = 30;
269 }
270
271draw:
272 memset(pong->gif->frame, 0, 64 * 32);
273 pong_draw_net(pong);
274 pong_draw_time(pong);
275 pong_draw_player(pong, 0, pong->player_left.y);
276 pong_draw_player(pong, 62, pong->player_right.y);
277 pong_draw_ball(pong);
278
279 return 8;
280}