clang -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name exec.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-eagerly-assume -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 -mthread-model posix -mdisable-fp-elim -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -resource-dir /usr/local/clang-7.0.0/lib/clang/7.0.0 -D HAVE_CONFIG_H -I . -I /home/travis/build/blogc/blogc -D PIC -internal-isystem /usr/local/include -internal-isystem /usr/local/clang-7.0.0/lib/clang/7.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -fdebug-compilation-dir /home/travis/build/blogc/blogc/build -ferror-limit 19 -fmessage-length 0 -fobjc-runtime=gcc -fdiagnostics-show-option -analyzer-output=html -o /home/travis/build/blogc/blogc/build/reports/2019-07-15-203554-7047-1 -x c /home/travis/build/blogc/blogc/src/blogc-make/exec.c -faddrsig
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | #ifdef HAVE_CONFIG_H1 |
10 | #include <config.h> |
11 | #endif /* HAVE_CONFIG_H */ |
12 | |
13 | #include <stdbool.h> |
14 | #include <stdlib.h> |
15 | #include <stdio.h> |
16 | #include <string.h> |
17 | #include <unistd.h> |
18 | #include <sys/wait.h> |
19 | #include <errno(*__errno_location ()).h> |
20 | #include <libgen.h> |
21 | #include "../common/compat.h" |
22 | #include "../common/error.h" |
23 | #include "../common/file.h" |
24 | #include "../common/utils.h" |
25 | #include "ctx.h" |
26 | #include "exec.h" |
27 | #include "settings.h" |
28 | |
29 | |
30 | char* |
31 | bm_exec_find_binary(const char *argv0, const char *bin, const char *env) |
32 | { |
33 | #ifdef MAKE_EMBEDDED |
34 | |
35 | |
36 | |
37 | if (argv0 != NULL((void*)0) && bin != NULL((void*)0) && (0 == strcmp(bin, "blogc"))) { |
38 | return bc_shell_quote(argv0); |
39 | } |
40 | #endif |
41 | |
42 | |
43 | const char *env_bin = getenv(env); |
44 | if (env_bin != NULL((void*)0)) { |
45 | return bc_shell_quote(env_bin); |
46 | } |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | if (argv0 != NULL((void*)0) && (NULL((void*)0) != strchr(argv0, '/'))) { |
57 | char *path = bc_strdup(argv0); |
58 | char *dir = bc_strdup(dirname(path)); |
59 | free(path); |
60 | char *tmp = bc_strdup_printf("%s/%s", dir, bin); |
61 | free(dir); |
62 | if (0 == access(tmp, X_OK1)) { |
63 | char *rv = bc_shell_quote(tmp); |
64 | free(tmp); |
65 | return rv; |
66 | } |
67 | free(tmp); |
68 | } |
69 | |
70 | |
71 | return bc_strdup(bin); |
72 | } |
73 | |
74 | |
75 | int |
76 | bm_exec_command(const char *cmd, const char *input, char **output, |
77 | char **error, bc_error_t **err) |
78 | { |
79 | if (err == NULL((void*)0) || *err != NULL((void*)0)) |
| |
80 | return 1; |
81 | |
82 | int fd_in[2]; |
83 | if (-1 == pipe(fd_in)) { |
| 11 | | Assuming the condition is false | |
|
| |
84 | *err = bc_error_new_printf(BLOGC_MAKE_ERROR_EXEC, |
85 | "Failed to create stdin pipe: %s", strerror(errno(*__errno_location ()))); |
86 | return 1; |
87 | } |
88 | |
89 | int fd_out[2]; |
90 | if (-1 == pipe(fd_out)) { |
| 13 | | Assuming the condition is false | |
|
| |
91 | *err = bc_error_new_printf(BLOGC_MAKE_ERROR_EXEC, |
92 | "Failed to create stdout pipe: %s", strerror(errno(*__errno_location ()))); |
93 | close(fd_in[0]); |
94 | close(fd_in[1]); |
95 | return 1; |
96 | } |
97 | |
98 | int fd_err[2]; |
99 | if (-1 == pipe(fd_err)) { |
| 15 | | Assuming the condition is false | |
|
| |
100 | *err = bc_error_new_printf(BLOGC_MAKE_ERROR_EXEC, |
101 | "Failed to create stderr pipe: %s", strerror(errno(*__errno_location ()))); |
102 | close(fd_in[0]); |
103 | close(fd_in[1]); |
104 | close(fd_out[0]); |
105 | close(fd_out[1]); |
106 | return 1; |
107 | } |
108 | |
109 | pid_t pid = fork(); |
110 | if (pid == -1) { |
| 17 | | Assuming the condition is false | |
|
| |
111 | *err = bc_error_new_printf(BLOGC_MAKE_ERROR_EXEC, |
112 | "Failed to fork: %s", strerror(errno(*__errno_location ()))); |
113 | close(fd_in[0]); |
114 | close(fd_in[1]); |
115 | close(fd_out[0]); |
116 | close(fd_out[1]); |
117 | close(fd_err[0]); |
118 | close(fd_err[1]); |
119 | return 1; |
120 | } |
121 | |
122 | |
123 | if (pid == 0) { |
| 19 | | Assuming 'pid' is not equal to 0 | |
|
| |
124 | close(fd_in[1]); |
125 | close(fd_out[0]); |
126 | close(fd_err[0]); |
127 | |
128 | dup2(fd_in[0], STDIN_FILENO0); |
129 | dup2(fd_out[1], STDOUT_FILENO1); |
130 | dup2(fd_err[1], STDERR_FILENO2); |
131 | |
132 | char *const argv[] = { |
133 | "/bin/sh", |
134 | "-c", |
135 | (char*) cmd, |
136 | NULL((void*)0), |
137 | }; |
138 | |
139 | execv(argv[0], argv); |
140 | |
141 | exit(1); |
142 | } |
143 | |
144 | |
145 | close(fd_in[0]); |
146 | close(fd_out[1]); |
147 | close(fd_err[1]); |
148 | |
149 | if (input != NULL((void*)0)) { |
| 21 | | Assuming 'input' is equal to NULL | |
|
| |
150 | if (-1 == write(fd_in[1], input, strlen(input))) { |
151 | *err = bc_error_new_printf(BLOGC_MAKE_ERROR_EXEC, |
152 | "Failed to write to stdin pipe: %s", strerror(errno(*__errno_location ()))); |
153 | close(fd_in[1]); |
154 | close(fd_out[0]); |
155 | close(fd_err[0]); |
156 | return 1; |
157 | } |
158 | } |
159 | |
160 | close(fd_in[1]); |
161 | |
162 | char buffer[BC_FILE_CHUNK_SIZE1024]; |
163 | ssize_t s; |
164 | |
165 | bc_string_t *out = NULL((void*)0); |
166 | while(0 != (s = read(fd_out[0], buffer, BC_FILE_CHUNK_SIZE1024))) { |
| 23 | | Assuming the condition is false | |
|
| 24 | | Loop condition is false. Execution continues on line 180 | |
|
167 | if (s == -1) { |
168 | *err = bc_error_new_printf(BLOGC_MAKE_ERROR_EXEC, |
169 | "Failed to read from stdout pipe: %s", strerror(errno(*__errno_location ()))); |
170 | close(fd_out[0]); |
171 | close(fd_err[0]); |
172 | bc_string_free(out, true1); |
173 | return 1; |
174 | } |
175 | if (out == NULL((void*)0)) { |
176 | out = bc_string_new(); |
177 | } |
178 | bc_string_append_len(out, buffer, s); |
179 | } |
180 | if (out != NULL((void*)0)) { |
| |
181 | *output = bc_string_free(out, false0); |
182 | } |
183 | close(fd_out[0]); |
184 | |
185 | out = NULL((void*)0); |
186 | while(0 != (s = read(fd_err[0], buffer, BC_FILE_CHUNK_SIZE1024))) { |
| 26 | | Assuming the condition is false | |
|
| 27 | | Loop condition is false. Execution continues on line 198 | |
|
187 | if (s == -1) { |
188 | *err = bc_error_new_printf(BLOGC_MAKE_ERROR_EXEC, |
189 | "Failed to read from stderr pipe: %s", strerror(errno(*__errno_location ()))); |
190 | close(fd_err[0]); |
191 | bc_string_free(out, true1); |
192 | return 1; |
193 | } |
194 | if (out == NULL((void*)0)) |
195 | out = bc_string_new(); |
196 | bc_string_append_len(out, buffer, s); |
197 | } |
198 | if (out != NULL((void*)0)) { |
| |
199 | *error = bc_string_free(out, false0); |
200 | } |
201 | close(fd_err[0]); |
202 | |
203 | int status; |
204 | waitpid(pid, &status, 0); |
205 | |
206 | return bc_compat_status_code(status); |
| 29 | | Returning without writing to '*output' | |
|
207 | } |
208 | |
209 | |
210 | static void |
211 | list_variables(const char *key, const char *value, bc_string_t *str) |
212 | { |
213 | char *tmp = bc_shell_quote(value); |
214 | bc_string_append_printf(str, " -D %s=%s", key, tmp); |
215 | free(tmp); |
216 | } |
217 | |
218 | |
219 | char* |
220 | bm_exec_build_blogc_cmd(const char *blogc_bin, bm_settings_t *settings, |
221 | bc_trie_t *global_variables, bc_trie_t *local_variables, const char *print, |
222 | bool_Bool listing, const char *listing_entry, const char *template, |
223 | const char *output, bool_Bool dev, bool_Bool sources_stdin) |
224 | { |
225 | bc_string_t *rv = bc_string_new(); |
226 | |
227 | const char *locale = NULL((void*)0); |
228 | if (settings != NULL((void*)0)) { |
229 | locale = bc_trie_lookup(settings->settings, "locale"); |
230 | } |
231 | if (locale != NULL((void*)0)) { |
232 | char *tmp = bc_shell_quote(locale); |
233 | bc_string_append_printf(rv, "LC_ALL=%s ", tmp); |
234 | free(tmp); |
235 | } |
236 | |
237 | bc_string_append(rv, blogc_bin); |
238 | |
239 | if (settings != NULL((void*)0)) { |
240 | if (settings->tags != NULL((void*)0)) { |
241 | char *tags = bc_strv_join(settings->tags, " "); |
242 | bc_string_append_printf(rv, " -D MAKE_TAGS='%s'", tags); |
243 | free(tags); |
244 | } |
245 | |
246 | bc_trie_foreach(settings->global, |
247 | (bc_trie_foreach_func_t) list_variables, rv); |
248 | } |
249 | |
250 | bc_trie_foreach(global_variables, (bc_trie_foreach_func_t) list_variables, rv); |
251 | bc_trie_foreach(local_variables, (bc_trie_foreach_func_t) list_variables, rv); |
252 | |
253 | if (dev) { |
254 | bc_string_append(rv, " -D MAKE_ENV_DEV=1 -D MAKE_ENV='dev'"); |
255 | } |
256 | |
257 | if (print != NULL((void*)0)) { |
258 | bc_string_append_printf(rv, " -p %s", print); |
259 | } |
260 | |
261 | if (listing) { |
262 | bc_string_append(rv, " -l"); |
263 | if (listing_entry != NULL((void*)0)) { |
264 | char *tmp = bc_shell_quote(listing_entry); |
265 | bc_string_append_printf(rv, " -e %s", tmp); |
266 | free(tmp); |
267 | } |
268 | } |
269 | |
270 | if (template != NULL((void*)0)) { |
271 | char *tmp = bc_shell_quote(template); |
272 | bc_string_append_printf(rv, " -t %s", tmp); |
273 | free(tmp); |
274 | } |
275 | |
276 | if (output != NULL((void*)0)) { |
277 | char *tmp = bc_shell_quote(output); |
278 | bc_string_append_printf(rv, " -o %s", tmp); |
279 | free(tmp); |
280 | } |
281 | |
282 | if (sources_stdin) { |
283 | bc_string_append(rv, " -i"); |
284 | } |
285 | |
286 | return bc_string_free(rv, false0); |
287 | } |
288 | |
289 | |
290 | int |
291 | bm_exec_blogc(bm_ctx_t *ctx, bc_trie_t *global_variables, bc_trie_t *local_variables, |
292 | bool_Bool listing, bm_filectx_t *listing_entry, bm_filectx_t *template, |
293 | bm_filectx_t *output, bc_slist_t *sources, bool_Bool only_first_source) |
294 | { |
295 | if (ctx == NULL((void*)0)) |
296 | return 1; |
297 | |
298 | bc_string_t *input = bc_string_new(); |
299 | for (bc_slist_t *l = sources; l != NULL((void*)0); l = l->next) { |
300 | bc_string_append_printf(input, "%s\n", ((bm_filectx_t*) l->data)->path); |
301 | if (only_first_source) |
302 | break; |
303 | } |
304 | |
305 | char *cmd = bm_exec_build_blogc_cmd(ctx->blogc, ctx->settings, global_variables, |
306 | local_variables, NULL((void*)0), listing, listing_entry == NULL((void*)0) ? NULL((void*)0) : listing_entry->path, |
307 | template->path, output->path, ctx->dev, input->len > 0); |
308 | |
309 | if (ctx->verbose) |
310 | printf("%s\n", cmd); |
311 | else |
312 | printf(" BLOGC %s\n", output->short_path); |
313 | fflush(stdoutstdout); |
314 | |
315 | char *out = NULL((void*)0); |
316 | char *err = NULL((void*)0); |
317 | bc_error_t *error = NULL((void*)0); |
318 | |
319 | int rv = bm_exec_command(cmd, input->str, &out, &err, &error); |
320 | |
321 | if (error != NULL((void*)0)) { |
322 | bc_error_print(error, "blogc-make"); |
323 | free(cmd); |
324 | free(out); |
325 | free(err); |
326 | bc_string_free(input, true1); |
327 | bc_error_free(error); |
328 | return 1; |
329 | } |
330 | |
331 | if (rv != 0 && ctx->verbose) { |
332 | fprintf(stderrstderr, |
333 | "blogc-make: error: Failed to execute command.\n" |
334 | "\n" |
335 | "STATUS CODE: %d\n", rv); |
336 | if (input->len > 0) { |
337 | fprintf(stderrstderr, "\nSTDIN:\n" |
338 | "----------------------------->8-----------------------------\n" |
339 | "%s\n" |
340 | "----------------------------->8-----------------------------\n", |
341 | bc_str_strip(input->str)); |
342 | } |
343 | if (out != NULL((void*)0)) { |
344 | fprintf(stderrstderr, "\nSTDOUT:\n" |
345 | "----------------------------->8-----------------------------\n" |
346 | "%s\n" |
347 | "----------------------------->8-----------------------------\n", |
348 | bc_str_strip(out)); |
349 | } |
350 | if (err != NULL((void*)0)) { |
351 | fprintf(stderrstderr, "\nSTDERR:\n" |
352 | "----------------------------->8-----------------------------\n" |
353 | "%s\n" |
354 | "----------------------------->8-----------------------------\n", |
355 | bc_str_strip(err)); |
356 | } |
357 | fprintf(stderrstderr, "\n"); |
358 | } |
359 | else if (err != NULL((void*)0)) { |
360 | fprintf(stderrstderr, "%s\n", err); |
361 | } |
362 | |
363 | bc_string_free(input, true1); |
364 | free(cmd); |
365 | free(out); |
366 | free(err); |
367 | |
368 | return rv == 127 ? 1 : rv; |
369 | } |
370 | |
371 | |
372 | char* |
373 | bm_exec_blogc_get_variable(bm_ctx_t *ctx, bc_trie_t *global_variables, |
374 | bc_trie_t *local_variables, const char *variable, bool_Bool listing, |
375 | bc_slist_t *sources, bool_Bool only_first_source) |
376 | { |
377 | if (ctx == NULL((void*)0)) |
| 1 | Assuming 'ctx' is not equal to NULL | |
|
| |
378 | return NULL((void*)0); |
379 | |
380 | bc_string_t *input = bc_string_new(); |
381 | for (bc_slist_t *l = sources; l != NULL((void*)0); l = l->next) { |
| 3 | | Assuming 'l' is equal to NULL | |
|
| 4 | | Loop condition is false. Execution continues on line 387 | |
|
382 | bc_string_append_printf(input, "%s\n", ((bm_filectx_t*) l->data)->path); |
383 | if (only_first_source) |
384 | break; |
385 | } |
386 | |
387 | char *cmd = bm_exec_build_blogc_cmd(ctx->blogc, ctx->settings, global_variables, |
388 | local_variables, variable, listing, NULL((void*)0), NULL((void*)0), NULL((void*)0), ctx->dev, input->len > 0); |
| 5 | | Assuming the condition is false | |
|
389 | |
390 | if (ctx->verbose) |
| 6 | | Assuming the condition is false | |
|
| |
391 | printf("%s\n", cmd); |
392 | fflush(stdoutstdout); |
393 | |
394 | char *out = NULL((void*)0); |
| 8 | | 'out' initialized to a null pointer value | |
|
395 | char *err = NULL((void*)0); |
396 | bc_error_t *error = NULL((void*)0); |
397 | |
398 | int rv = bm_exec_command(cmd, input->str, &out, &err, &error); |
| 9 | | Calling 'bm_exec_command' | |
|
| 30 | | Returning from 'bm_exec_command' | |
|
399 | |
400 | if (error != NULL((void*)0)) { |
| |
401 | bc_error_print(error, "blogc-make"); |
402 | bc_error_free(error); |
403 | bc_string_free(input, true1); |
404 | free(cmd); |
405 | free(out); |
406 | free(err); |
407 | return NULL((void*)0); |
408 | } |
409 | |
410 | if (rv != 0) { |
| 32 | | Assuming 'rv' is equal to 0 | |
|
| |
411 | fprintf(stderrstderr, "blogc-make: error: %s\n", bc_str_strip(err)); |
412 | bc_string_free(input, true1); |
413 | free(cmd); |
414 | free(out); |
415 | free(err); |
416 | return NULL((void*)0); |
417 | } |
418 | |
419 | char *val = bc_strndup(out, strlen(out) - 1); |
| 34 | | Null pointer passed as an argument to a 'nonnull' parameter |
|
420 | |
421 | bc_string_free(input, true1); |
422 | free(cmd); |
423 | free(out); |
424 | free(err); |
425 | |
426 | return val; |
427 | } |
428 | |
429 | |
430 | int |
431 | bm_exec_blogc_runserver(bm_ctx_t *ctx, const char *host, const char *port, |
432 | const char *threads) |
433 | { |
434 | if (ctx == NULL((void*)0)) |
435 | return 1; |
436 | |
437 | bc_string_t *cmd = bc_string_new(); |
438 | |
439 | bc_string_append(cmd, ctx->blogc_runserver); |
440 | |
441 | if (host != NULL((void*)0)) { |
442 | char *tmp = bc_shell_quote(host); |
443 | bc_string_append_printf(cmd, " -t %s", tmp); |
444 | free(tmp); |
445 | } |
446 | |
447 | if (port != NULL((void*)0)) { |
448 | char *tmp = bc_shell_quote(port); |
449 | bc_string_append_printf(cmd, " -p %s", tmp); |
450 | free(tmp); |
451 | } |
452 | |
453 | if (threads != NULL((void*)0)) { |
454 | char *tmp = bc_shell_quote(threads); |
455 | bc_string_append_printf(cmd, " -m %s", tmp); |
456 | free(tmp); |
457 | } |
458 | |
459 | char *tmp = bc_shell_quote(ctx->output_dir); |
460 | bc_string_append_printf(cmd, " %s", tmp); |
461 | free(tmp); |
462 | |
463 | if (ctx->verbose) |
464 | printf("%s\n\n", cmd->str); |
465 | else |
466 | printf("\n"); |
467 | fflush(stdoutstdout); |
468 | |
469 | |
470 | int status = system(cmd->str); |
471 | int rv = bc_compat_status_code(status); |
472 | bc_string_free(cmd, true1); |
473 | |
474 | if (rv != 0 && rv != 130) { |
475 | if (rv == 127) { |
476 | fprintf(stderrstderr, |
477 | "blogc-make: error: blogc-runserver command not found. Maybe " |
478 | "it is not installed?\n"); |
479 | rv = 1; |
480 | } |
481 | else { |
482 | fprintf(stderrstderr, |
483 | "blogc-make: error: Failed to execute command, returned " |
484 | "status code: %d\n", rv); |
485 | } |
486 | } |
487 | |
488 | return rv; |
489 | } |