Bug Summary

File:samples/clock/gifenc.c
Warning:line 214, column 28
Although the value stored to 'node' is used in the enclosing expression, the value is never actually read from 'node'

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 gifenc.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-17-154318-1429062-1 -x c /home/buildbot/lwan-worker/clang-analyze/build/src/samples/clock/gifenc.c
1/*
2 * All of the source code and documentation for gifenc is released into the
3 * public domain and provided without warranty of any kind.
4 *
5 * Author: Marcel Rodrigues <https://github.com/lecram>
6 */
7#include "gifenc.h"
8
9#include <fcntl.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <sys/stat.h>
14#include <sys/types.h>
15#include <unistd.h>
16
17static uint8_t vga[0x30] = {
18 0x00, 0x00, 0x00, 0xAA, 0x00, 0x00, 0x00, 0xAA, 0x00, 0xAA, 0x55, 0x00,
19 0x00, 0x00, 0xAA, 0xAA, 0x00, 0xAA, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
20 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0xFF, 0xFF, 0x55,
21 0x55, 0x55, 0xFF, 0xFF, 0x55, 0xFF, 0x55, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
22};
23
24#pragma GCC diagnostic ignored "-Wconversion"
25#pragma GCC diagnostic ignored "-Wsign-conversion"
26#pragma GCC diagnostic ignored "-Wpointer-sign"
27
28struct Node {
29 uint16_t key;
30 struct Node *children[];
31};
32typedef struct Node Node;
33
34static Node *new_node(uint16_t key, int degree)
35{
36 Node *node = calloc(1, sizeof(*node) + degree * sizeof(Node *));
37 if (node)
38 node->key = key;
39 return node;
40}
41
42static Node *new_trie(int degree, int *nkeys)
43{
44 Node *root = new_node(0, degree);
45 /* Create nodes for single pixels. */
46 for (*nkeys = 0; *nkeys < degree; (*nkeys)++)
47 root->children[*nkeys] = new_node(*nkeys, degree);
48 *nkeys += 2; /* skip clear code and stop code */
49 return root;
50}
51
52static void del_trie(Node *root, int degree)
53{
54 if (!root)
55 return;
56 for (int i = 0; i < degree; i++)
57 del_trie(root->children[i], degree);
58 free(root);
59}
60
61static void put_loop(ge_GIF *gif, uint16_t loop);
62
63static void write_num(struct lwan_strbuf *buf, int16_t num)
64{
65 lwan_strbuf_append_char(buf, num & 0xff);
66 lwan_strbuf_append_char(buf, num >> 8);
67}
68
69ge_GIF *ge_new_gif(struct lwan_strbuf *buf,
70 uint16_t width,
71 uint16_t height,
72 uint8_t *palette,
73 int depth,
74 int loop)
75{
76 int i, r, g, b, v;
77 ge_GIF *gif = calloc(1, sizeof(*gif) + 2 * width * height);
78
79 if (!gif)
80 goto no_gif;
81
82 gif->w = width;
83 gif->h = height;
84 gif->depth = depth > 1 ? depth : 2;
85 gif->frame = (uint8_t *)&gif[1];
86 gif->back = &gif->frame[width * height];
87 gif->buf = buf;
88
89 lwan_strbuf_append_str(buf, "GIF89a", 6);
90 write_num(buf, width);
91 write_num(buf, height);
92 lwan_strbuf_append_str(buf, (const char[]){0xF0 | (depth - 1), 0x00, 0x00},
93 3);
94
95 if (palette) {
96 lwan_strbuf_append_str(buf, palette, 3 << depth);
97 } else if (depth <= 4) {
98 lwan_strbuf_append_str(buf, vga, 3 << depth);
99 } else {
100 lwan_strbuf_append_str(buf, vga, sizeof(vga));
101
102 i = 0x10;
103 for (r = 0; r < 6; r++) {
104 for (g = 0; g < 6; g++) {
105 for (b = 0; b < 6; b++) {
106 lwan_strbuf_append_str(
107 buf, (const char[]){r * 51, g * 51, b * 51}, 3);
108 if (++i == 1 << depth)
109 goto done_gct;
110 }
111 }
112 }
113 for (i = 1; i <= 24; i++) {
114 v = i * 0xFF / 25;
115 lwan_strbuf_append_str(buf, (const char[]){v, v, v}, 3);
116 }
117 }
118
119done_gct:
120 if (loop >= 0 && loop <= 0xFFFF)
121 put_loop(gif, (uint16_t)loop);
122 return gif;
123
124no_gif:
125 return NULL((void*)0);
126}
127
128static void put_loop(ge_GIF *gif, uint16_t loop)
129{
130 lwan_strbuf_append_str(gif->buf, (const char[]){'!', 0xFF, 0x0B}, 3);
131 lwan_strbuf_append_str(gif->buf, "NETSCAPE2.0", 11);
132 lwan_strbuf_append_str(gif->buf, (const char[]){0x03, 0x01}, 2);
133 write_num(gif->buf, loop);
134 lwan_strbuf_append_char(gif->buf, '\0');
135}
136
137/* Add packed key to buffer, updating offset and partial.
138 * gif->offset holds position to put next *bit*
139 * gif->partial holds bits to include in next byte */
140static void put_key(ge_GIF *gif, uint16_t key, int key_size)
141{
142 int byte_offset, bit_offset, bits_to_write;
143
144 byte_offset = gif->offset / 8;
145 bit_offset = gif->offset % 8;
146 gif->partial |= ((uint32_t)key) << bit_offset;
147 bits_to_write = bit_offset + key_size;
148
149 while (bits_to_write >= 8) {
150 gif->buffer[byte_offset++] = gif->partial & 0xFF;
151
152 if (byte_offset == 0xFF) {
153 lwan_strbuf_append_char(gif->buf, 0xff);
154 lwan_strbuf_append_str(gif->buf, gif->buffer, 0xff);
155
156 byte_offset = 0;
157 }
158
159 gif->partial >>= 8;
160 bits_to_write -= 8;
161 }
162 gif->offset = (gif->offset + key_size) % (0xFF * 8);
163}
164
165static void end_key(ge_GIF *gif)
166{
167 int byte_offset;
168
169 byte_offset = gif->offset / 8;
170 if (gif->offset % 8)
171 gif->buffer[byte_offset++] = gif->partial & 0xFF;
172
173 lwan_strbuf_append_char(gif->buf, byte_offset);
174 lwan_strbuf_append_str(gif->buf, gif->buffer, byte_offset);
175 lwan_strbuf_append_char(gif->buf, '\0');
176
177 gif->offset = gif->partial = 0;
178}
179
180static void
181put_image(ge_GIF *gif, uint16_t w, uint16_t h, uint16_t x, uint16_t y)
182{
183 int nkeys, key_size, i, j;
184 Node *node, *child, *root;
185 int degree = 1 << gif->depth;
186
187 lwan_strbuf_append_char(gif->buf, ',');
188 write_num(gif->buf, x);
189 write_num(gif->buf, y);
190 write_num(gif->buf, w);
191 write_num(gif->buf, h);
192 lwan_strbuf_append_str(gif->buf, (const char[]){0x00, gif->depth}, 2);
193
194 root = node = new_trie(degree, &nkeys);
195 key_size = gif->depth + 1;
196 put_key(gif, degree, key_size); /* clear code */
197
198 for (i = y; i < y + h; i++) {
199 for (j = x; j < x + w; j++) {
200 uint8_t pixel = gif->frame[i * gif->w + j] & (degree - 1);
201 child = node->children[pixel];
202
203 if (child) {
204 node = child;
205 } else {
206 put_key(gif, node->key, key_size);
207 if (nkeys < 0x1000) {
208 if (nkeys == (1 << key_size))
209 key_size++;
210 node->children[pixel] = new_node(nkeys++, degree);
211 } else {
212 put_key(gif, degree, key_size); /* clear code */
213 del_trie(root, degree);
214 root = node = new_trie(degree, &nkeys);
Although the value stored to 'node' is used in the enclosing expression, the value is never actually read from 'node'
215 key_size = gif->depth + 1;
216 }
217 node = root->children[pixel];
218 }
219 }
220 }
221
222 put_key(gif, node->key, key_size);
223 put_key(gif, degree + 1, key_size); /* stop code */
224 end_key(gif);
225 del_trie(root, degree);
226}
227
228static int
229get_bbox(ge_GIF *gif, uint16_t *w, uint16_t *h, uint16_t *x, uint16_t *y)
230{
231 int i, j, k;
232 int left, right, top, bottom;
233
234 left = gif->w;
235 right = 0;
236 top = gif->h;
237 bottom = 0;
238 k = 0;
239 for (i = 0; i < gif->h; i++) {
240 for (j = 0; j < gif->w; j++, k++) {
241 if (gif->frame[k] != gif->back[k]) {
242 if (j < left)
243 left = j;
244 if (j > right)
245 right = j;
246 if (i < top)
247 top = i;
248 if (i > bottom)
249 bottom = i;
250 }
251 }
252 }
253
254 if (left != gif->w && top != gif->h) {
255 *x = left;
256 *y = top;
257 *w = right - left + 1;
258 *h = bottom - top + 1;
259 return 1;
260 } else {
261 return 0;
262 }
263}
264
265static void set_delay(ge_GIF *gif, uint16_t d)
266{
267 lwan_strbuf_append_str(gif->buf, (const char[]){'!', 0xF9, 0x04, 0x04}, 4);
268 write_num(gif->buf, d);
269 lwan_strbuf_append_str(gif->buf, "\0\0", 2);
270}
271
272void ge_add_frame(ge_GIF *gif, uint16_t delay)
273{
274 uint16_t w, h, x, y;
275 uint8_t *tmp;
276
277 if (delay)
278 set_delay(gif, delay);
279 if (gif->nframes == 0) {
280 w = gif->w;
281 h = gif->h;
282 x = y = 0;
283 } else if (!get_bbox(gif, &w, &h, &x, &y)) {
284 /* image's not changed; save one pixel just to add delay */
285 w = h = 1;
286 x = y = 0;
287 }
288 put_image(gif, w, h, x, y);
289 gif->nframes++;
290 tmp = gif->back;
291 gif->back = gif->frame;
292 gif->frame = tmp;
293}
294
295struct lwan_strbuf *ge_close_gif(ge_GIF *gif)
296{
297 struct lwan_strbuf *buf = gif->buf;
298
299 lwan_strbuf_append_char(gif->buf, ';');
300 free(gif);
301
302 return buf;
303}