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 -mrelocation-model pic -pic-level 2 -pic-is-pie -mthread-model posix -mdisable-fp-elim -fmath-errno -masm-verbose -mconstructor-aliases -fno-plt -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -resource-dir /usr/lib/clang/9.0.1 -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/9.0.1/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 -fobjc-runtime=gcc -fdiagnostics-show-option -analyzer-output=html -faddrsig -o /home/buildbot/lwan-worker/clang-analyze/CLANG/2020-04-10-051146-3697238-1 -x c /home/buildbot/lwan-worker/clang-analyze/build/src/samples/clock/gifenc.c
1 | |
2 | |
3 | |
4 | |
5 | |
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 | |
17 | static 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 | |
28 | struct Node { |
29 | uint16_t key; |
30 | struct Node *children[]; |
31 | }; |
32 | typedef struct Node Node; |
33 | |
34 | static 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 | |
42 | static Node *new_trie(int degree, int *nkeys) |
43 | { |
44 | Node *root = new_node(0, degree); |
45 | |
46 | for (*nkeys = 0; *nkeys < degree; (*nkeys)++) |
47 | root->children[*nkeys] = new_node(*nkeys, degree); |
48 | *nkeys += 2; |
49 | return root; |
50 | } |
51 | |
52 | static 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 | |
61 | static void put_loop(ge_GIF *gif, uint16_t loop); |
62 | |
63 | static 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 | |
69 | ge_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 | |
119 | done_gct: |
120 | if (loop >= 0 && loop <= 0xFFFF) |
121 | put_loop(gif, (uint16_t)loop); |
122 | return gif; |
123 | |
124 | no_gif: |
125 | return NULL; |
126 | } |
127 | |
128 | static 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 | |
138 | |
139 | |
140 | static 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 | |
165 | static 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 | |
180 | static void |
181 | put_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); |
197 | |
198 | for (i = y; i < y + h; i++) { |
| 6 | | Assuming the condition is true | |
|
| 7 | | Loop condition is true. Entering loop body | |
|
| 17 | | Assuming the condition is false | |
|
| 18 | | Loop condition is false. Execution continues on line 222 | |
|
199 | for (j = x; j < x + w; j++) { |
| 8 | | Assuming the condition is true | |
|
| 9 | | Loop condition is true. Entering loop body | |
|
| 15 | | Assuming the condition is false | |
|
| 16 | | Loop condition is false. Execution continues on line 198 | |
|
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)) |
| 12 | | Assuming the condition is false | |
|
| |
209 | key_size++; |
210 | node->children[pixel] = new_node(nkeys++, degree); |
211 | } else { |
212 | put_key(gif, degree, key_size); |
213 | del_trie(root, degree); |
214 | root = node = new_trie(degree, &nkeys); |
215 | key_size = gif->depth + 1; |
216 | } |
217 | node = root->children[pixel]; |
| 14 | | Null pointer value stored to 'node' | |
|
218 | } |
219 | } |
220 | } |
221 | |
222 | put_key(gif, node->key, key_size); |
| 19 | | Access to field 'key' results in a dereference of a null pointer (loaded from variable 'node') |
|
223 | put_key(gif, degree + 1, key_size); |
224 | end_key(gif); |
225 | del_trie(root, degree); |
226 | } |
227 | |
228 | static int |
229 | get_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 | |
265 | static 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 | |
272 | void 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) { |
| 3 | | Assuming field 'nframes' is equal to 0 | |
|
| |
280 | w = gif->w; |
281 | h = gif->h; |
282 | x = y = 0; |
283 | } else if (!get_bbox(gif, &w, &h, &x, &y)) { |
284 | |
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 | |
295 | struct 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 | } |