clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name roff_escape.c -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 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/mandoc/obj -resource-dir /usr/local/llvm16/lib/clang/16 -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/usr/src/usr.bin/mandoc/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/usr.bin/mandoc/roff_escape.c
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | #include <assert.h> |
23 | #include <ctype.h> |
24 | #include <limits.h> |
25 | #include <stdio.h> |
26 | #include <string.h> |
27 | |
28 | #include "mandoc.h" |
29 | #include "roff.h" |
30 | #include "roff_int.h" |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | enum mandoc_esc |
39 | mandoc_escape(const char **rendarg, const char **rarg, int *rargl) |
40 | { |
41 | int iarg, iendarg, iend; |
42 | enum mandoc_esc rval; |
43 | |
44 | rval = roff_escape(--*rendarg, 0, 0, |
45 | NULL, NULL, &iarg, &iendarg, &iend); |
46 | assert(rval != ESCAPE_EXPAND); |
47 | if (rarg != NULL) |
48 | *rarg = *rendarg + iarg; |
49 | if (rargl != NULL) |
50 | *rargl = iendarg - iarg; |
51 | *rendarg += iend; |
52 | return rval; |
53 | } |
54 | |
55 | |
56 | |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | |
63 | |
64 | |
65 | enum mandoc_esc |
66 | roff_escape(const char *buf, const int ln, const int aesc, |
67 | int *resc, int *rnam, int *rarg, int *rendarg, int *rend) |
68 | { |
69 | int iesc; |
70 | int inam; |
71 | int iarg; |
72 | int iendarg; |
73 | int iend; |
74 | int sesc, snam, sarg, sendarg, send; |
75 | int escterm; |
76 | int maxl; |
77 | int argl; |
| 1 | 'argl' declared without an initial value | |
|
78 | int c, i; |
79 | int valid_A; |
80 | enum mandoc_esc rval; |
81 | enum mandoc_esc stype; |
82 | enum mandocerr err; |
83 | char term; |
84 | |
85 | |
86 | |
87 | |
88 | |
89 | |
90 | iesc = inam = aesc; |
91 | do { |
| 2 | | Loop condition is false. Exiting loop | |
|
92 | inam++; |
93 | } while (buf[inam] == 'E'); |
94 | |
95 | |
96 | |
97 | |
98 | |
99 | |
100 | iarg = iendarg = iend = inam + 1; |
101 | maxl = INT_MAX; |
102 | term = '\0'; |
103 | err = MANDOCERR_OK; |
104 | switch (buf[inam]) { |
| 3 | | Control jumps to 'case 67:' at line 210 | |
|
105 | |
106 | |
107 | |
108 | case '!': |
109 | case '?': |
110 | case 'r': |
111 | rval = ESCAPE_UNSUPP; |
112 | goto out; |
113 | |
114 | case '%': |
115 | case '&': |
116 | case ')': |
117 | case ',': |
118 | case '/': |
119 | case '^': |
120 | case 'a': |
121 | case 'd': |
122 | case 't': |
123 | case 'u': |
124 | case '{': |
125 | case '|': |
126 | case '}': |
127 | rval = ESCAPE_IGNORE; |
128 | goto out; |
129 | |
130 | case '\0': |
131 | iendarg = --iend; |
132 | |
133 | case '.': |
134 | case '\\': |
135 | default: |
136 | iarg--; |
137 | rval = ESCAPE_UNDEF; |
138 | goto out; |
139 | |
140 | case ' ': |
141 | case '\'': |
142 | case '-': |
143 | case '0': |
144 | case ':': |
145 | case '_': |
146 | case '`': |
147 | case 'e': |
148 | case '~': |
149 | iarg--; |
150 | argl = 1; |
151 | rval = ESCAPE_SPECIAL; |
152 | goto out; |
153 | case 'p': |
154 | rval = ESCAPE_BREAK; |
155 | goto out; |
156 | case 'c': |
157 | rval = ESCAPE_NOSPACE; |
158 | goto out; |
159 | case 'z': |
160 | rval = ESCAPE_SKIPCHAR; |
161 | goto out; |
162 | |
163 | |
164 | |
165 | case '$': |
166 | case '*': |
167 | case 'V': |
168 | case 'g': |
169 | case 'n': |
170 | rval = ESCAPE_EXPAND; |
171 | break; |
172 | case 'F': |
173 | case 'M': |
174 | case 'O': |
175 | case 'Y': |
176 | case 'k': |
177 | case 'm': |
178 | rval = ESCAPE_IGNORE; |
179 | break; |
180 | case '(': |
181 | case '[': |
182 | rval = ESCAPE_SPECIAL; |
183 | iendarg = iend = --iarg; |
184 | break; |
185 | case 'f': |
186 | rval = ESCAPE_FONT; |
187 | break; |
188 | |
189 | |
190 | |
191 | case 'A': |
192 | case 'B': |
193 | case 'w': |
194 | rval = ESCAPE_EXPAND; |
195 | term = '\b'; |
196 | break; |
197 | case 'D': |
198 | case 'H': |
199 | case 'L': |
200 | case 'R': |
201 | case 'S': |
202 | case 'X': |
203 | case 'Z': |
204 | case 'b': |
205 | case 'v': |
206 | case 'x': |
207 | rval = ESCAPE_IGNORE; |
208 | term = '\b'; |
209 | break; |
210 | case 'C': |
211 | rval = ESCAPE_SPECIAL; |
212 | term = '\b'; |
213 | break; |
214 | case 'N': |
215 | rval = ESCAPE_NUMBERED; |
216 | term = '\b'; |
217 | break; |
218 | case 'h': |
219 | rval = ESCAPE_HORIZ; |
220 | term = '\b'; |
221 | break; |
222 | case 'l': |
223 | rval = ESCAPE_HLINE; |
224 | term = '\b'; |
225 | break; |
226 | case 'o': |
227 | rval = ESCAPE_OVERSTRIKE; |
228 | term = '\b'; |
229 | break; |
230 | |
231 | |
232 | |
233 | case 's': |
234 | rval = ESCAPE_IGNORE; |
235 | if (buf[iarg] == '+' || buf[iarg] == '-'|| |
236 | buf[iarg] == ASCII_HYPH) |
237 | iarg++; |
238 | switch (buf[iarg]) { |
239 | case '(': |
240 | maxl = 2; |
241 | iarg++; |
242 | break; |
243 | case '[': |
244 | term = ']'; |
245 | iarg++; |
246 | break; |
247 | case '\'': |
248 | term = '\''; |
249 | iarg++; |
250 | break; |
251 | case '1': |
252 | case '2': |
253 | case '3': |
254 | if (buf[iarg - 1] == 's' && |
255 | isdigit((unsigned char)buf[iarg + 1])) { |
256 | maxl = 2; |
257 | break; |
258 | } |
259 | |
260 | default: |
261 | maxl = 1; |
262 | break; |
263 | } |
264 | iendarg = iend = iarg; |
265 | } |
266 | |
267 | |
268 | |
269 | escterm = 0; |
| 4 | | Execution continues on line 269 | |
|
270 | stype = ESCAPE_EXPAND; |
271 | if ((term == '\b' || (term == '\0' && maxl == INT_MAX)) && |
| |
272 | buf[iarg] == buf[iesc]) { |
| 5 | | Assuming the condition is true | |
|
273 | stype = roff_escape(buf, ln, iendarg, |
274 | &sesc, &snam, &sarg, &sendarg, &send); |
275 | if (stype == ESCAPE_EXPAND) |
| 7 | | Assuming 'stype' is not equal to ESCAPE_EXPAND | |
|
| |
276 | goto out_sub; |
277 | } |
278 | |
279 | if (term == '\b') { |
| |
280 | if (stype == ESCAPE_UNDEF) |
| 10 | | Assuming 'stype' is not equal to ESCAPE_UNDEF | |
|
281 | iarg++; |
282 | if (stype != ESCAPE_EXPAND && stype != ESCAPE_UNDEF) { |
283 | if (strchr("BHLRSNhlvx", buf[inam]) != NULL && |
| 11 | | Assuming the condition is true | |
|
| |
284 | strchr(" ,.0DLOXYZ^abdhlortuvx|~", |
| 12 | | Assuming the condition is true | |
|
285 | buf[snam]) != NULL) { |
286 | err = MANDOCERR_ESC_DELIM; |
287 | iend = send; |
288 | iarg = iendarg = sesc; |
289 | goto out; |
| 14 | | Control jumps to line 508 | |
|
290 | } |
291 | escterm = 1; |
292 | iarg = send; |
293 | term = buf[snam]; |
294 | } else if (strchr("BDHLRSvxNhl", buf[inam]) != NULL && |
295 | strchr(" %&()*+-./0123456789:<=>", buf[iarg]) != NULL) { |
296 | err = MANDOCERR_ESC_DELIM; |
297 | if (rval != ESCAPE_EXPAND) |
298 | rval = ESCAPE_ERROR; |
299 | if (buf[inam] != 'D') { |
300 | iendarg = iend = iarg + 1; |
301 | goto out; |
302 | } |
303 | } |
304 | if (term == '\b') |
305 | term = buf[iarg++]; |
306 | } else if (term == '\0' && maxl == INT_MAX) { |
307 | if (buf[inam] == 'n' && (buf[iarg] == '+' || buf[iarg] == '-')) |
308 | iarg++; |
309 | switch (buf[iarg]) { |
310 | case '(': |
311 | maxl = 2; |
312 | iarg++; |
313 | break; |
314 | case '[': |
315 | if (buf[++iarg] == ' ') { |
316 | iendarg = iend = iarg + 1; |
317 | err = MANDOCERR_ESC_ARG; |
318 | rval = ESCAPE_ERROR; |
319 | goto out; |
320 | } |
321 | term = ']'; |
322 | break; |
323 | default: |
324 | maxl = 1; |
325 | break; |
326 | } |
327 | } |
328 | |
329 | |
330 | |
331 | valid_A = 1; |
332 | iendarg = iarg; |
333 | while (maxl > 0) { |
334 | if (buf[iendarg] == '\0') { |
335 | err = MANDOCERR_ESC_INCOMPLETE; |
336 | if (rval != ESCAPE_EXPAND && |
337 | rval != ESCAPE_OVERSTRIKE) |
338 | rval = ESCAPE_ERROR; |
339 | |
340 | if (strchr("Aow", buf[inam]) == NULL) |
341 | iendarg = iarg; |
342 | break; |
343 | } |
344 | if (escterm == 0 && buf[iendarg] == term) { |
345 | iend = iendarg + 1; |
346 | break; |
347 | } |
348 | if (buf[iendarg] == buf[iesc]) { |
349 | stype = roff_escape(buf, ln, iendarg, |
350 | &sesc, &snam, &sarg, &sendarg, &send); |
351 | if (stype == ESCAPE_EXPAND) |
352 | goto out_sub; |
353 | iend = send; |
354 | if (escterm == 1 && |
355 | (buf[snam] == term || buf[inam] == 'N')) |
356 | break; |
357 | if (stype != ESCAPE_UNDEF) |
358 | valid_A = 0; |
359 | iendarg = send; |
360 | } else if (buf[inam] == 'N' && |
361 | isdigit((unsigned char)buf[iendarg]) == 0) { |
362 | iend = iendarg + 1; |
363 | break; |
364 | } else { |
365 | if (buf[iendarg] == ' ' || buf[iendarg] == '\t') |
366 | valid_A = 0; |
367 | if (maxl != INT_MAX) |
368 | maxl--; |
369 | iend = ++iendarg; |
370 | } |
371 | } |
372 | |
373 | |
374 | |
375 | argl = iendarg - iarg; |
376 | switch (buf[inam]) { |
377 | case '*': |
378 | if (resc == NULL && argl == 2 && |
379 | buf[iarg] == '.' && buf[iarg + 1] == 'T') |
380 | rval = ESCAPE_DEVICE; |
381 | break; |
382 | case 'A': |
383 | if (valid_A == 0) |
384 | iendarg = iarg; |
385 | break; |
386 | case 'O': |
387 | switch (buf[iarg]) { |
388 | case '0': |
389 | rval = ESCAPE_UNSUPP; |
390 | break; |
391 | case '1': |
392 | case '2': |
393 | case '3': |
394 | case '4': |
395 | if (argl == 1) |
396 | rval = ESCAPE_IGNORE; |
397 | else { |
398 | err = MANDOCERR_ESC_ARG; |
399 | rval = ESCAPE_ERROR; |
400 | } |
401 | break; |
402 | case '5': |
403 | if (buf[iarg - 1] == '[') |
404 | rval = ESCAPE_UNSUPP; |
405 | else { |
406 | err = MANDOCERR_ESC_ARG; |
407 | rval = ESCAPE_ERROR; |
408 | } |
409 | break; |
410 | default: |
411 | err = MANDOCERR_ESC_ARG; |
412 | rval = ESCAPE_ERROR; |
413 | break; |
414 | } |
415 | break; |
416 | default: |
417 | break; |
418 | } |
419 | |
420 | switch (rval) { |
421 | case ESCAPE_FONT: |
422 | rval = mandoc_font(buf + iarg, argl); |
423 | if (rval == ESCAPE_ERROR) |
424 | err = MANDOCERR_ESC_ARG; |
425 | break; |
426 | |
427 | case ESCAPE_SPECIAL: |
428 | if (argl == 0) { |
429 | err = MANDOCERR_ESC_BADCHAR; |
430 | rval = ESCAPE_ERROR; |
431 | break; |
432 | } |
433 | |
434 | |
435 | |
436 | |
437 | |
438 | |
439 | |
440 | |
441 | if (term != '\0' && argl == 1 && buf[iarg] != '-') { |
442 | err = MANDOCERR_ESC_BADCHAR; |
443 | rval = ESCAPE_ERROR; |
444 | break; |
445 | } |
446 | |
447 | |
448 | |
449 | if (buf[iarg] == 'c') { |
450 | if (argl < 6 || argl > 7 || |
451 | strncmp(buf + iarg, "char", 4) != 0 || |
452 | (int)strspn(buf + iarg + 4, "0123456789") |
453 | + 4 < argl) |
454 | break; |
455 | c = 0; |
456 | for (i = iarg; i < iendarg; i++) |
457 | c = 10 * c + (buf[i] - '0'); |
458 | if (c < 0x21 || (c > 0x7e && c < 0xa0) || c > 0xff) { |
459 | err = MANDOCERR_ESC_BADCHAR; |
460 | break; |
461 | } |
462 | iarg += 4; |
463 | rval = ESCAPE_NUMBERED; |
464 | break; |
465 | } |
466 | |
467 | |
468 | |
469 | |
470 | |
471 | |
472 | |
473 | |
474 | if (buf[iarg] != 'u' || argl < 5 || argl > 7) |
475 | break; |
476 | if (argl == 7 && |
477 | (buf[iarg + 1] != '1' || buf[iarg + 2] != '0')) { |
478 | err = MANDOCERR_ESC_BADCHAR; |
479 | break; |
480 | } |
481 | if (argl == 6 && buf[iarg + 1] == '0') { |
482 | err = MANDOCERR_ESC_BADCHAR; |
483 | break; |
484 | } |
485 | if (argl == 5 && buf[iarg + 1] == 'D' && |
486 | strchr("89ABCDEF", buf[iarg + 2]) != NULL) { |
487 | err = MANDOCERR_ESC_BADCHAR; |
488 | break; |
489 | } |
490 | if ((int)strspn(buf + iarg + 1, "0123456789ABCDEFabcdef") |
491 | + 1 == argl) |
492 | rval = ESCAPE_UNICODE; |
493 | break; |
494 | default: |
495 | break; |
496 | } |
497 | goto out; |
498 | |
499 | out_sub: |
500 | iesc = sesc; |
501 | inam = snam; |
502 | iarg = sarg; |
503 | iendarg = sendarg; |
504 | iend = send; |
505 | rval = ESCAPE_EXPAND; |
506 | |
507 | out: |
508 | if (resc != NULL) |
| 15 | | Assuming 'resc' is equal to NULL | |
|
| |
509 | *resc = iesc; |
510 | if (rnam != NULL) |
| 17 | | Assuming 'rnam' is equal to NULL | |
|
| |
511 | *rnam = inam; |
512 | if (rarg != NULL) |
| 19 | | Assuming 'rarg' is equal to NULL | |
|
| |
513 | *rarg = iarg; |
514 | if (rendarg != NULL) |
| 21 | | Assuming 'rendarg' is equal to NULL | |
|
| |
515 | *rendarg = iendarg; |
516 | if (rend != NULL) |
| 23 | | Assuming 'rend' is equal to NULL | |
|
| |
517 | *rend = iend; |
518 | if (ln == 0) |
| 25 | | Assuming 'ln' is not equal to 0 | |
|
| |
519 | return rval; |
520 | |
521 | |
522 | |
523 | |
524 | |
525 | |
526 | switch (rval) { |
| 27 | | Control jumps to 'case ESCAPE_SPECIAL:' at line 534 | |
|
527 | case ESCAPE_UNSUPP: |
528 | err = MANDOCERR_ESC_UNSUPP; |
529 | break; |
530 | case ESCAPE_UNDEF: |
531 | if (buf[inam] != '\\' && buf[inam] != '.') |
532 | err = MANDOCERR_ESC_UNDEF; |
533 | break; |
534 | case ESCAPE_SPECIAL: |
535 | if (mchars_spec2cp(buf + iarg, argl) >= 0) |
| 28 | | 2nd function call argument is an uninitialized value |
|
536 | err = MANDOCERR_OK; |
537 | else if (err == MANDOCERR_OK) |
538 | err = MANDOCERR_ESC_UNKCHAR; |
539 | break; |
540 | default: |
541 | break; |
542 | } |
543 | if (err != MANDOCERR_OK) |
544 | mandoc_msg(err, ln, iesc, "%.*s", iend - iesc, buf + iesc); |
545 | return rval; |
546 | } |