clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ddcutil_config_file.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 -mframe-pointer=none -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib/llvm-11/lib/clang/11.0.0 -D HAVE_CONFIG_H -I . -I ../.. -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/libdrm -D PIC -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-11/lib/clang/11.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir /shared/playproj/i2c/src/util -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o ddcutil_config_file.plist -x c ddcutil_config_file.c
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | #include <assert.h> |
13 | #include <errno.h> |
14 | #include <stdbool.h> |
15 | #include <stddef.h> |
16 | #include <stdio.h> |
17 | #include <wordexp.h> |
18 | |
19 | #include "config_file.h" |
20 | #include "string_util.h" |
21 | #include "xdg_util.h" |
22 | |
23 | #include "ddcutil_config_file.h" |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | int tokenize_init_line(char * string, char ***tokens_loc) { |
34 | bool debug = false; |
35 | wordexp_t p; |
36 | int flags = WRDE_NOCMD; |
37 | if (debug) |
38 | flags |= WRDE_SHOWERR; |
39 | wordexp(string, &p, flags); |
40 | *tokens_loc = p.we_wordv; |
41 | if (debug) { |
42 | ntsa_show(p.we_wordv); |
43 | printf("(%s) Returning: %ld\n", __func__, p.we_wordc); |
44 | } |
45 | return p.we_wordc; |
46 | } |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | |
63 | int read_ddcutil_config_file( |
64 | const char * ddcutil_application, |
65 | char *** tokenized_options_loc, |
66 | char** untokenized_option_string_loc, |
67 | GPtrArray * errmsgs, |
68 | char ** config_fn_loc, |
69 | bool verbose) |
70 | { |
71 | bool debug = false; |
72 | |
73 | int result = 0; |
74 | int token_ct = 0; |
75 | *tokenized_options_loc = NULL; |
| 2 | | Null pointer value stored to 'cmd_prefix_tokens' | |
|
76 | *untokenized_option_string_loc = NULL; |
77 | *config_fn_loc = NULL; |
78 | char ** prefix_tokens = NULL; |
79 | |
80 | char * config_fn = find_xdg_config_file("ddcutil", "ddcutilrc"); |
81 | *config_fn_loc = config_fn; |
82 | if (!config_fn) { |
| 3 | | Assuming 'config_fn' is null | |
|
| |
83 | if (debug) |
| |
84 | printf("(%s) Configuration file not found\n", __func__); |
85 | result = 0; |
86 | token_ct = 0; |
87 | goto bye; |
| 6 | | Control jumps to line 137 | |
|
88 | } |
89 | |
90 | GHashTable * config_hash = NULL; |
91 | if (debug) |
92 | printf("(%s) Before load_configuration_file(), config_fn = %s\n", |
93 | __func__, config_fn); |
94 | int load_rc = load_configuration_file(config_fn, &config_hash, errmsgs, false); |
95 | if (debug) |
96 | fprintf(stderr, "load_configuration file() returned %d\n", load_rc); |
97 | if (load_rc < 0) { |
98 | if (load_rc == -ENOENT) { |
99 | result = 0; |
100 | token_ct = 0; |
101 | } |
102 | |
103 | else { |
104 | if (verbose) |
105 | fprintf(stderr, "Error loading configuration file: %d\n", load_rc); |
106 | result = load_rc; |
107 | } |
108 | } |
109 | if (verbose && errmsgs && errmsgs->len > 0) { |
110 | fprintf(stderr, "Error(s) processing configuration file %s\n", config_fn); |
111 | for (int ndx = 0; ndx < errmsgs->len; ndx++) { |
112 | fprintf(stderr, " %s\n", (char*) g_ptr_array_index(errmsgs, ndx)); |
113 | } |
114 | } |
115 | |
116 | if (load_rc == 0 || load_rc == -EBADMSG) { |
117 | if (debug) { |
118 | dump_ini_hash(config_hash); |
119 | } |
120 | char * global_options = get_config_value(config_hash, "global", "options"); |
121 | char * ddcutil_options = get_config_value(config_hash, ddcutil_application, "options"); |
122 | |
123 | char * combined_options = g_strdup_printf("%s %s", |
124 | (global_options) ? global_options : "", |
125 | (ddcutil_options) ? ddcutil_options : ""); |
126 | if (debug) |
127 | printf("(%s) combined_options= |%s|\n", __func__, combined_options); |
128 | *untokenized_option_string_loc = combined_options; |
129 | |
130 | if (combined_options) { |
131 | token_ct = tokenize_init_line(combined_options, &prefix_tokens); |
132 | *tokenized_options_loc = prefix_tokens; |
133 | } |
134 | } |
135 | |
136 | bye: |
137 | if (debug) { |
| |
138 | printf("(%s) Returning untokenized options: |%s|, token_ct = %d, *config_fn_loc=%s\n", |
139 | __func__, *untokenized_option_string_loc, token_ct, *config_fn_loc); |
140 | printf("(%s) prefix_tokens:\n", __func__); |
141 | ntsa_show(prefix_tokens); |
142 | printf("(%s) Returning: %d\n", __func__, result); |
143 | } |
144 | return result; |
145 | } |
146 | |
147 | |
148 | |
149 | |
150 | |
151 | |
152 | |
153 | |
154 | |
155 | |
156 | |
157 | |
158 | int merge_command_tokens( |
159 | int old_argc, |
160 | char ** old_argv, |
161 | int config_token_ct, |
162 | char ** config_tokens, |
163 | char *** new_argv_loc) |
164 | { |
165 | bool debug = false; |
166 | |
167 | |
168 | *new_argv_loc = old_argv; |
169 | int new_argc = old_argc; |
170 | |
171 | if (config_token_ct > 0) { |
| |
172 | int new_ct = config_token_ct + old_argc + 1; |
173 | if (debug) |
| |
174 | printf("(%s) config_token_ct = %d, argc=%d, new_ct=%d\n", |
175 | __func__, config_token_ct, old_argc, new_ct); |
176 | char ** combined = calloc(new_ct, sizeof(char *)); |
177 | combined[0] = old_argv[0]; |
178 | int new_ndx = 1; |
179 | for (int prefix_ndx = 0; prefix_ndx < config_token_ct; prefix_ndx++, new_ndx++) { |
| 18 | | Loop condition is true. Entering loop body | |
|
180 | combined[new_ndx] = config_tokens[prefix_ndx]; |
| 19 | | Array access (from variable 'config_tokens') results in a null pointer dereference |
|
181 | } |
182 | for (int old_ndx = 1; old_ndx < old_argc; old_ndx++, new_ndx++) { |
183 | combined[new_ndx] = old_argv[old_ndx]; |
184 | } |
185 | combined[new_ndx] = NULL; |
186 | if (debug) |
187 | printf("(%s) Final new_ndx = %d\n", __func__, new_ndx); |
188 | *new_argv_loc = combined; |
189 | new_argc = new_ct - 1; |
190 | assert(new_argc == ntsa_length(combined)); |
191 | } |
192 | |
193 | if (debug) { |
194 | printf("(%s) Returning %d, *new_argv_loc=%p\n", __func__, new_argc, *new_argv_loc); |
195 | printf("(%s) tokens:\n", __func__); |
196 | ntsa_show(*new_argv_loc); |
197 | } |
198 | |
199 | return new_argc; |
200 | } |
201 | |
202 | |
203 | |
204 | |
205 | |
206 | |
207 | |
208 | |
209 | |
210 | |
211 | |
212 | |
213 | |
214 | |
215 | |
216 | int read_parse_and_merge_config_file( |
217 | const char * ddcutil_application, |
218 | int old_argc, |
219 | char ** old_argv, |
220 | char *** new_argv_loc, |
221 | char** untokenized_cmd_prefix_loc, |
222 | char** configure_fn_loc, |
223 | GPtrArray * errmsgs) |
224 | { |
225 | bool debug = false; |
226 | char **cmd_prefix_tokens = NULL; |
227 | |
228 | *new_argv_loc = old_argv; |
229 | int new_argc = old_argc; |
230 | |
231 | int read_config_rc = |
232 | read_ddcutil_config_file( |
| 1 | Calling 'read_ddcutil_config_file' | |
|
| 8 | | Returning from 'read_ddcutil_config_file' | |
|
233 | ddcutil_application, |
234 | &cmd_prefix_tokens, |
235 | untokenized_cmd_prefix_loc, |
236 | errmsgs, |
237 | configure_fn_loc, |
238 | debug); |
239 | int prefix_token_ct = ntsa_length(cmd_prefix_tokens); |
240 | if (debug) |
| |
241 | printf("(%s) get_config_file() returned %d, configure_fn: %s\n", |
242 | __func__, read_config_rc, *configure_fn_loc); |
243 | |
244 | if (prefix_token_ct < 0) { |
| 10 | | Assuming 'prefix_token_ct' is >= 0 | |
|
| |
245 | new_argc = -1; |
246 | } |
247 | else if (prefix_token_ct > 0) { |
| 12 | | Assuming 'prefix_token_ct' is > 0 | |
|
| |
248 | new_argc = merge_command_tokens( |
| 15 | | Calling 'merge_command_tokens' | |
|
249 | old_argc, |
250 | old_argv, |
251 | prefix_token_ct, |
252 | cmd_prefix_tokens, |
| 14 | | Passing null pointer value via 4th parameter 'config_tokens' | |
|
253 | new_argv_loc); |
254 | } |
255 | if (cmd_prefix_tokens) |
256 | ntsa_free(cmd_prefix_tokens, false); |
257 | |
258 | if (debug) { |
259 | printf("(%s) Returning %d, *new_argv_loc=%p\n", __func__, new_argc, *new_argv_loc); |
260 | printf("(%s) tokens:\n", __func__); |
261 | ntsa_show(*new_argv_loc); |
262 | } |
263 | |
264 | return new_argc; |
265 | } |
266 | |