clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name rpc_parse.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 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -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/rpcgen/obj -resource-dir /usr/local/lib/clang/13.0.0 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.bin/rpcgen/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -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/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.bin/rpcgen/rpc_parse.c
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | #include <stdio.h> |
39 | #include <stdlib.h> |
40 | #include <string.h> |
41 | #include "rpc/types.h" |
42 | #include "rpc_scan.h" |
43 | #include "rpc_parse.h" |
44 | #include "rpc_util.h" |
45 | |
46 | #define ARGNAME "arg" |
47 | |
48 | static void isdefined(definition *); |
49 | static void def_struct(definition *); |
50 | static void def_program(definition *); |
51 | static void def_enum(definition *); |
52 | static void def_const(definition *); |
53 | static void def_union(definition *); |
54 | static void def_typedef(definition *); |
55 | static void get_declaration(declaration *, defkind); |
56 | static void get_prog_declaration(declaration *, defkind, int); |
57 | static void get_type(char **, char **, defkind); |
58 | static void unsigned_dec(char **); |
59 | |
60 | |
61 | |
62 | |
63 | definition * |
64 | get_definition(void) |
65 | { |
66 | definition *defp; |
67 | token tok; |
68 | |
69 | defp = malloc(sizeof(definition)); |
70 | get_token(&tok); |
71 | switch (tok.kind) { |
| 1 | Control jumps to 'case TOK_TYPEDEF:' at line 78 | |
|
72 | case TOK_STRUCT: |
73 | def_struct(defp); |
74 | break; |
75 | case TOK_UNION: |
76 | def_union(defp); |
77 | break; |
78 | case TOK_TYPEDEF: |
79 | def_typedef(defp); |
| |
80 | break; |
81 | case TOK_ENUM: |
82 | def_enum(defp); |
83 | break; |
84 | case TOK_PROGRAM: |
85 | def_program(defp); |
86 | break; |
87 | case TOK_CONST: |
88 | def_const(defp); |
89 | break; |
90 | case TOK_EOF: |
91 | free(defp); |
92 | return (NULL); |
93 | default: |
94 | error("definition keyword expected"); |
95 | } |
96 | scan(TOK_SEMICOLON, &tok); |
97 | isdefined(defp); |
98 | return (defp); |
99 | } |
100 | |
101 | static void |
102 | isdefined(defp) |
103 | definition *defp; |
104 | { |
105 | STOREVAL(&defined, defp); |
106 | } |
107 | |
108 | static void |
109 | def_struct(defp) |
110 | definition *defp; |
111 | { |
112 | token tok; |
113 | declaration dec; |
114 | decl_list *decls; |
115 | decl_list **tailp; |
116 | |
117 | defp->def_kind = DEF_STRUCT; |
118 | |
119 | scan(TOK_IDENT, &tok); |
120 | defp->def_name = tok.str; |
121 | scan(TOK_LBRACE, &tok); |
122 | tailp = &defp->def.st.decls; |
123 | do { |
124 | get_declaration(&dec, DEF_STRUCT); |
125 | decls = malloc(sizeof(decl_list)); |
126 | decls->decl = dec; |
127 | *tailp = decls; |
128 | tailp = &decls->next; |
129 | scan(TOK_SEMICOLON, &tok); |
130 | peek(&tok); |
131 | } while (tok.kind != TOK_RBRACE); |
132 | get_token(&tok); |
133 | *tailp = NULL; |
134 | } |
135 | |
136 | static void |
137 | def_program(defp) |
138 | definition *defp; |
139 | { |
140 | token tok; |
141 | declaration dec; |
142 | decl_list *decls; |
143 | decl_list **tailp; |
144 | version_list *vlist; |
145 | version_list **vtailp; |
146 | proc_list *plist; |
147 | proc_list **ptailp; |
148 | int num_args; |
149 | bool_t isvoid = FALSE; |
150 | defp->def_kind = DEF_PROGRAM; |
151 | scan(TOK_IDENT, &tok); |
152 | defp->def_name = tok.str; |
153 | scan(TOK_LBRACE, &tok); |
154 | vtailp = &defp->def.pr.versions; |
155 | tailp = &defp->def.st.decls; |
156 | scan(TOK_VERSION, &tok); |
157 | do { |
158 | scan(TOK_IDENT, &tok); |
159 | vlist = malloc(sizeof(version_list)); |
160 | vlist->vers_name = tok.str; |
161 | scan(TOK_LBRACE, &tok); |
162 | ptailp = &vlist->procs; |
163 | do { |
164 | |
165 | plist = malloc(sizeof(proc_list)); |
166 | get_type(&plist->res_prefix, &plist->res_type, |
167 | DEF_PROGRAM); |
168 | if (streq(plist->res_type, "opaque")) { |
169 | error("illegal result type"); |
170 | } |
171 | scan(TOK_IDENT, &tok); |
172 | plist->proc_name = tok.str; |
173 | scan(TOK_LPAREN, &tok); |
174 | |
175 | num_args = 1; |
176 | isvoid = FALSE; |
177 | |
178 | |
179 | |
180 | |
181 | get_prog_declaration(&dec, DEF_PROGRAM, num_args); |
182 | if (streq(dec.type, "void")) |
183 | isvoid = TRUE; |
184 | decls = malloc(sizeof(decl_list)); |
185 | plist->args.decls = decls; |
186 | decls->decl = dec; |
187 | tailp = &decls->next; |
188 | |
189 | while (peekscan(TOK_COMMA, &tok)) { |
190 | num_args++; |
191 | get_prog_declaration(&dec, DEF_STRUCT, |
192 | num_args); |
193 | decls = malloc(sizeof(decl_list)); |
194 | decls->decl = dec; |
195 | *tailp = decls; |
196 | if (streq(dec.type, "void")) |
197 | isvoid = TRUE; |
198 | tailp = &decls->next; |
199 | } |
200 | |
201 | if (!newstyle && num_args > 1) { |
202 | error("only one argument is allowed"); |
203 | } |
204 | if (isvoid && num_args > 1) { |
205 | error("illegal use of void in program definition"); |
206 | } |
207 | *tailp = NULL; |
208 | scan(TOK_RPAREN, &tok); |
209 | scan(TOK_EQUAL, &tok); |
210 | scan_num(&tok); |
211 | scan(TOK_SEMICOLON, &tok); |
212 | plist->proc_num = tok.str; |
213 | plist->arg_num = num_args; |
214 | *ptailp = plist; |
215 | ptailp = &plist->next; |
216 | peek(&tok); |
217 | } while (tok.kind != TOK_RBRACE); |
218 | *ptailp = NULL; |
219 | *vtailp = vlist; |
220 | vtailp = &vlist->next; |
221 | scan(TOK_RBRACE, &tok); |
222 | scan(TOK_EQUAL, &tok); |
223 | scan_num(&tok); |
224 | vlist->vers_num = tok.str; |
225 | |
226 | for (plist = vlist->procs; plist != NULL; |
227 | plist = plist->next) { |
228 | plist->args.argname = make_argname(plist->proc_name, |
229 | vlist->vers_num); |
230 | |
231 | } |
232 | scan(TOK_SEMICOLON, &tok); |
233 | scan2(TOK_VERSION, TOK_RBRACE, &tok); |
234 | } while (tok.kind == TOK_VERSION); |
235 | scan(TOK_EQUAL, &tok); |
236 | scan_num(&tok); |
237 | defp->def.pr.prog_num = tok.str; |
238 | *vtailp = NULL; |
239 | } |
240 | |
241 | |
242 | static void |
243 | def_enum(defp) |
244 | definition *defp; |
245 | { |
246 | token tok; |
247 | enumval_list *elist; |
248 | enumval_list **tailp; |
249 | |
250 | defp->def_kind = DEF_ENUM; |
251 | scan(TOK_IDENT, &tok); |
252 | defp->def_name = tok.str; |
253 | scan(TOK_LBRACE, &tok); |
254 | tailp = &defp->def.en.vals; |
255 | do { |
256 | scan(TOK_IDENT, &tok); |
257 | elist = malloc(sizeof(enumval_list)); |
258 | elist->name = tok.str; |
259 | elist->assignment = NULL; |
260 | scan3(TOK_COMMA, TOK_RBRACE, TOK_EQUAL, &tok); |
261 | if (tok.kind == TOK_EQUAL) { |
262 | scan_num(&tok); |
263 | elist->assignment = tok.str; |
264 | scan2(TOK_COMMA, TOK_RBRACE, &tok); |
265 | } |
266 | *tailp = elist; |
267 | tailp = &elist->next; |
268 | } while (tok.kind != TOK_RBRACE); |
269 | *tailp = NULL; |
270 | } |
271 | |
272 | static void |
273 | def_const(defp) |
274 | definition *defp; |
275 | { |
276 | token tok; |
277 | |
278 | defp->def_kind = DEF_CONST; |
279 | scan(TOK_IDENT, &tok); |
280 | defp->def_name = tok.str; |
281 | scan(TOK_EQUAL, &tok); |
282 | scan2(TOK_IDENT, TOK_STRCONST, &tok); |
283 | defp->def.co = tok.str; |
284 | } |
285 | |
286 | static void |
287 | def_union(defp) |
288 | definition *defp; |
289 | { |
290 | token tok; |
291 | declaration dec; |
292 | case_list *cases; |
293 | case_list **tailp; |
294 | int flag; |
295 | |
296 | defp->def_kind = DEF_UNION; |
297 | scan(TOK_IDENT, &tok); |
298 | defp->def_name = tok.str; |
299 | scan(TOK_SWITCH, &tok); |
300 | scan(TOK_LPAREN, &tok); |
301 | get_declaration(&dec, DEF_UNION); |
302 | defp->def.un.enum_decl = dec; |
303 | tailp = &defp->def.un.cases; |
304 | scan(TOK_RPAREN, &tok); |
305 | scan(TOK_LBRACE, &tok); |
306 | scan(TOK_CASE, &tok); |
307 | while (tok.kind == TOK_CASE) { |
308 | scan2(TOK_IDENT, TOK_CHARCONST, &tok); |
309 | cases = malloc(sizeof(case_list)); |
310 | cases->case_name = tok.str; |
311 | scan(TOK_COLON, &tok); |
312 | |
313 | flag=0; |
314 | if (peekscan(TOK_CASE,&tok)) { |
315 | do { |
316 | scan2(TOK_IDENT, TOK_CHARCONST, &tok); |
317 | cases->contflag=1; |
318 | *tailp = cases; |
319 | tailp = &cases->next; |
320 | cases = malloc(sizeof(case_list)); |
321 | cases->case_name = tok.str; |
322 | scan(TOK_COLON, &tok); |
323 | } while (peekscan(TOK_CASE,&tok)); |
324 | } else if (flag) { |
325 | *tailp = cases; |
326 | tailp = &cases->next; |
327 | cases = malloc(sizeof(case_list)); |
328 | } |
329 | get_declaration(&dec, DEF_UNION); |
330 | cases->case_decl = dec; |
331 | cases->contflag=0; |
332 | *tailp = cases; |
333 | tailp = &cases->next; |
334 | scan(TOK_SEMICOLON, &tok); |
335 | |
336 | scan3(TOK_CASE, TOK_DEFAULT, TOK_RBRACE, &tok); |
337 | } |
338 | *tailp = NULL; |
339 | |
340 | if (tok.kind == TOK_DEFAULT) { |
341 | scan(TOK_COLON, &tok); |
342 | get_declaration(&dec, DEF_UNION); |
343 | defp->def.un.default_decl = malloc(sizeof(declaration)); |
344 | *defp->def.un.default_decl = dec; |
345 | scan(TOK_SEMICOLON, &tok); |
346 | scan(TOK_RBRACE, &tok); |
347 | } else { |
348 | defp->def.un.default_decl = NULL; |
349 | } |
350 | } |
351 | |
352 | static char *reserved_words[] = { |
353 | "array", |
354 | "bytes", |
355 | "destroy", |
356 | "free", |
357 | "getpos", |
358 | "inline", |
359 | "pointer", |
360 | "reference", |
361 | "setpos", |
362 | "sizeof", |
363 | "union", |
364 | "vector", |
365 | NULL |
366 | }; |
367 | |
368 | static char *reserved_types[] = { |
369 | "opaque", |
370 | "string", |
371 | NULL |
372 | }; |
373 | |
374 | |
375 | |
376 | static void |
377 | check_type_name(char *name, int new_type) |
378 | { |
379 | int i; |
380 | char tmp[100]; |
381 | |
382 | for (i = 0; reserved_words[i] != NULL; i++) { |
383 | if (strcmp(name, reserved_words[i]) == 0) { |
384 | snprintf(tmp, sizeof tmp, |
385 | "illegal (reserved) name :\'%s\' in type definition", name); |
386 | error(tmp); |
387 | } |
388 | } |
389 | if (new_type) { |
390 | for (i = 0; reserved_types[i] != NULL; i++) { |
391 | if (strcmp(name, reserved_types[i]) == 0) { |
392 | snprintf(tmp, sizeof tmp, |
393 | "illegal (reserved) name :\'%s\' in" |
394 | " type definition", name); |
395 | error(tmp); |
396 | } |
397 | } |
398 | } |
399 | } |
400 | |
401 | static void |
402 | def_typedef(defp) |
403 | definition *defp; |
404 | { |
405 | declaration dec; |
406 | |
407 | defp->def_kind = DEF_TYPEDEF; |
408 | get_declaration(&dec, DEF_TYPEDEF); |
| 3 | | Calling 'get_declaration' | |
|
| 7 | | Returning from 'get_declaration' | |
|
409 | defp->def_name = dec.name; |
| 8 | | Assigned value is garbage or undefined |
|
410 | check_type_name(dec.name, 1); |
411 | defp->def.ty.old_prefix = dec.prefix; |
412 | defp->def.ty.old_type = dec.type; |
413 | defp->def.ty.rel = dec.rel; |
414 | defp->def.ty.array_max = dec.array_max; |
415 | } |
416 | |
417 | static void |
418 | get_declaration(dec, dkind) |
419 | declaration *dec; |
420 | defkind dkind; |
421 | { |
422 | token tok; |
423 | |
424 | get_type(&dec->prefix, &dec->type, dkind); |
425 | dec->rel = REL_ALIAS; |
426 | if (streq(dec->type, "void")) { |
| 4 | | Assuming the condition is true | |
|
| |
427 | return; |
| 6 | | Returning without writing to 'dec->name' | |
|
428 | } |
429 | |
430 | check_type_name(dec->type, 0); |
431 | |
432 | scan2(TOK_STAR, TOK_IDENT, &tok); |
433 | if (tok.kind == TOK_STAR) { |
434 | dec->rel = REL_POINTER; |
435 | scan(TOK_IDENT, &tok); |
436 | } |
437 | dec->name = tok.str; |
438 | if (peekscan(TOK_LBRACKET, &tok)) { |
439 | if (dec->rel == REL_POINTER) { |
440 | error("no array-of-pointer declarations -- use typedef"); |
441 | } |
442 | dec->rel = REL_VECTOR; |
443 | scan_num(&tok); |
444 | dec->array_max = tok.str; |
445 | scan(TOK_RBRACKET, &tok); |
446 | } else if (peekscan(TOK_LANGLE, &tok)) { |
447 | if (dec->rel == REL_POINTER) { |
448 | error("no array-of-pointer declarations -- use typedef"); |
449 | } |
450 | dec->rel = REL_ARRAY; |
451 | if (peekscan(TOK_RANGLE, &tok)) { |
452 | dec->array_max = "~0"; |
453 | } else { |
454 | scan_num(&tok); |
455 | dec->array_max = tok.str; |
456 | scan(TOK_RANGLE, &tok); |
457 | } |
458 | } |
459 | if (streq(dec->type, "opaque")) { |
460 | if (dec->rel != REL_ARRAY && dec->rel != REL_VECTOR) { |
461 | error("array declaration expected"); |
462 | } |
463 | } else if (streq(dec->type, "string")) { |
464 | if (dec->rel != REL_ARRAY) { |
465 | error("variable-length array declaration expected"); |
466 | } |
467 | } |
468 | } |
469 | |
470 | static void |
471 | get_prog_declaration(dec, dkind, num) |
472 | declaration *dec; |
473 | defkind dkind; |
474 | int num; |
475 | { |
476 | token tok; |
477 | |
478 | if (dkind == DEF_PROGRAM) { |
479 | peek(&tok); |
480 | if (tok.kind == TOK_RPAREN) { |
481 | dec->rel = REL_ALIAS; |
482 | dec->type = "void"; |
483 | dec->prefix = NULL; |
484 | dec->name = NULL; |
485 | return; |
486 | } |
487 | } |
488 | get_type(&dec->prefix, &dec->type, dkind); |
489 | dec->rel = REL_ALIAS; |
490 | if (peekscan(TOK_IDENT, &tok)) { |
491 | dec->name = (char *)strdup(tok.str); |
492 | if (dec->name == NULL) |
493 | error("out of memory"); |
494 | } else { |
495 | |
496 | if (asprintf(&dec->name, "%s%d", ARGNAME, num) == -1) |
497 | error("out of memory"); |
498 | } |
499 | |
500 | if (streq(dec->type, "void")) |
501 | return; |
502 | |
503 | if (streq(dec->type, "opaque")) |
504 | error("opaque -- illegal argument type"); |
505 | |
506 | if (peekscan(TOK_STAR, &tok)) { |
507 | if (streq(dec->type, "string")) |
508 | error("pointer to string not allowed in program arguments\n"); |
509 | |
510 | dec->rel = REL_POINTER; |
511 | if (peekscan(TOK_IDENT, &tok)) { |
512 | dec->name = (char *)strdup(tok.str); |
513 | if (dec->name == NULL) |
514 | error("out of memory"); |
515 | } |
516 | } |
517 | if (peekscan(TOK_LANGLE, &tok)) { |
518 | if (!streq(dec->type, "string")) |
519 | error("arrays cannot be declared as arguments to " |
520 | "procedures -- use typedef"); |
521 | dec->rel = REL_ARRAY; |
522 | if (peekscan(TOK_RANGLE, &tok)) { |
523 | dec->array_max = "~0"; |
524 | } else { |
525 | scan_num(&tok); |
526 | dec->array_max = tok.str; |
527 | scan(TOK_RANGLE, &tok); |
528 | } |
529 | } |
530 | if (streq(dec->type, "string")) { |
531 | |
532 | |
533 | |
534 | |
535 | if (dec->rel != REL_ARRAY) { |
536 | dec->rel = REL_ARRAY; |
537 | dec->array_max = "~0"; |
538 | } |
539 | } |
540 | } |
541 | |
542 | static void |
543 | get_type(prefixp, typep, dkind) |
544 | char **prefixp; |
545 | char **typep; |
546 | defkind dkind; |
547 | { |
548 | token tok; |
549 | |
550 | *prefixp = NULL; |
551 | get_token(&tok); |
552 | switch (tok.kind) { |
553 | case TOK_IDENT: |
554 | *typep = tok.str; |
555 | break; |
556 | case TOK_STRUCT: |
557 | case TOK_ENUM: |
558 | case TOK_UNION: |
559 | *prefixp = tok.str; |
560 | scan(TOK_IDENT, &tok); |
561 | *typep = tok.str; |
562 | break; |
563 | case TOK_UNSIGNED: |
564 | unsigned_dec(typep); |
565 | break; |
566 | case TOK_SHORT: |
567 | *typep = "short"; |
568 | (void) peekscan(TOK_INT, &tok); |
569 | break; |
570 | case TOK_LONG: |
571 | *typep = "long"; |
572 | (void) peekscan(TOK_INT, &tok); |
573 | break; |
574 | case TOK_HYPER: |
575 | *typep = "int64_t"; |
576 | (void) peekscan(TOK_INT, &tok); |
577 | break; |
578 | case TOK_VOID: |
579 | if (dkind != DEF_UNION && dkind != DEF_PROGRAM) { |
580 | error("voids allowed only inside union and program definitions with one argument"); |
581 | } |
582 | *typep = tok.str; |
583 | break; |
584 | case TOK_STRING: |
585 | case TOK_OPAQUE: |
586 | case TOK_CHAR: |
587 | case TOK_INT: |
588 | case TOK_FLOAT: |
589 | case TOK_DOUBLE: |
590 | case TOK_QUAD: |
591 | case TOK_BOOL: |
592 | *typep = tok.str; |
593 | break; |
594 | default: |
595 | error("expected type specifier"); |
596 | } |
597 | } |
598 | |
599 | static void |
600 | unsigned_dec(typep) |
601 | char **typep; |
602 | { |
603 | token tok; |
604 | |
605 | peek(&tok); |
606 | switch (tok.kind) { |
607 | case TOK_CHAR: |
608 | get_token(&tok); |
609 | *typep = "u_char"; |
610 | break; |
611 | case TOK_SHORT: |
612 | get_token(&tok); |
613 | *typep = "u_short"; |
614 | (void) peekscan(TOK_INT, &tok); |
615 | break; |
616 | case TOK_LONG: |
617 | get_token(&tok); |
618 | *typep = "u_long"; |
619 | (void) peekscan(TOK_INT, &tok); |
620 | break; |
621 | case TOK_HYPER: |
622 | get_token(&tok); |
623 | *typep = "u_int64_t"; |
624 | (void) peekscan(TOK_INT, &tok); |
625 | break; |
626 | case TOK_INT: |
627 | get_token(&tok); |
628 | *typep = "u_int"; |
629 | break; |
630 | default: |
631 | *typep = "u_int"; |
632 | break; |
633 | } |
634 | } |