Bug Summary

File:src/usr.bin/rpcgen/rpc_parse.c
Warning:line 409, column 17
Assigned value is garbage or undefined

Annotated Source Code

Press '?' to see keyboard shortcuts

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/* $OpenBSD: rpc_parse.c,v 1.20 2016/01/15 10:14:32 jasper Exp $ */
2/* $NetBSD: rpc_parse.c,v 1.5 1995/08/29 23:05:55 cgd Exp $ */
3
4/*
5 * Copyright (c) 2010, Oracle America, Inc.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials
16 * provided with the distribution.
17 * * Neither the name of the "Oracle America, Inc." nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
26 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
28 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35/*
36 * rpc_parse.c, Parser for the RPC protocol compiler
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" "arg"
47
48static void isdefined(definition *);
49static void def_struct(definition *);
50static void def_program(definition *);
51static void def_enum(definition *);
52static void def_const(definition *);
53static void def_union(definition *);
54static void def_typedef(definition *);
55static void get_declaration(declaration *, defkind);
56static void get_prog_declaration(declaration *, defkind, int);
57static void get_type(char **, char **, defkind);
58static void unsigned_dec(char **);
59
60/*
61 * return the next definition you see
62 */
63definition *
64get_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);
2
Calling 'def_typedef'
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((void *)0));
93 default:
94 error("definition keyword expected");
95 }
96 scan(TOK_SEMICOLON, &tok);
97 isdefined(defp);
98 return (defp);
99}
100
101static void
102isdefined(defp)
103 definition *defp;
104{
105 STOREVAL(&defined, defp)storeval(&defined,defp);
106}
107
108static void
109def_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((void *)0);
134}
135
136static void
137def_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_tint32_t isvoid = FALSE(0); /* whether first argument is void */
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 /* get result type */
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 /* get args - first one*/
175 num_args = 1;
176 isvoid = FALSE(0);
177 /* type of DEF_PROGRAM in the first
178 * get_prog_declaration and DEF_STURCT in the next
179 * allows void as argument if it is the only argument
180 */
181 get_prog_declaration(&dec, DEF_PROGRAM, num_args);
182 if (streq(dec.type, "void"))
183 isvoid = TRUE(1);
184 decls = malloc(sizeof(decl_list));
185 plist->args.decls = decls;
186 decls->decl = dec;
187 tailp = &decls->next;
188 /* get args */
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(1);
198 tailp = &decls->next;
199 }
200 /* multiple arguments are only allowed in newstyle */
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((void *)0);
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((void *)0);
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 /* make the argument structure name for each arg*/
226 for (plist = vlist->procs; plist != NULL((void *)0);
227 plist = plist->next) {
228 plist->args.argname = make_argname(plist->proc_name,
229 vlist->vers_num);
230 /* free the memory ??*/
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((void *)0);
239}
240
241
242static void
243def_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((void *)0);
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((void *)0);
270}
271
272static void
273def_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
286static void
287def_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 /* now peek at next token */
313 flag=0;
314 if (peekscan(TOK_CASE,&tok)) {
315 do {
316 scan2(TOK_IDENT, TOK_CHARCONST, &tok);
317 cases->contflag=1; /* continued case statement */
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; /* no continued case statement */
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((void *)0);
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((void *)0);
349 }
350}
351
352static 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((void *)0)
366};
367
368static char *reserved_types[] = {
369 "opaque",
370 "string",
371 NULL((void *)0)
372};
373
374/* check that the given name is not one that would eventually result in
375 xdr routines that would conflict with internal XDR routines. */
376static void
377check_type_name(char *name, int new_type)
378{
379 int i;
380 char tmp[100];
381
382 for (i = 0; reserved_words[i] != NULL((void *)0); 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((void *)0); 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
401static void
402def_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
417static void
418get_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
5
Taking true branch
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"; /* unspecified size, use max */
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
470static void
471get_prog_declaration(dec, dkind, num)
472 declaration *dec;
473 defkind dkind;
474 int num; /* arg number */
475{
476 token tok;
477
478 if (dkind == DEF_PROGRAM) {
479 peek(&tok);
480 if (tok.kind == TOK_RPAREN) { /* no arguments */
481 dec->rel = REL_ALIAS;
482 dec->type = "void";
483 dec->prefix = NULL((void *)0);
484 dec->name = NULL((void *)0);
485 return;
486 }
487 }
488 get_type(&dec->prefix, &dec->type, dkind);
489 dec->rel = REL_ALIAS;
490 if (peekscan(TOK_IDENT, &tok)) { /* optional name of argument */
491 dec->name = (char *)strdup(tok.str);
492 if (dec->name == NULL((void *)0))
493 error("out of memory");
494 } else {
495 /* default name of argument */
496 if (asprintf(&dec->name, "%s%d", ARGNAME"arg", 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)) { /* optional name of argument */
512 dec->name = (char *)strdup(tok.str);
513 if (dec->name == NULL((void *)0))
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";/* unspecified size, use max */
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 /* .x specifies just string as
532 * type of argument
533 * - make it string<>
534 */
535 if (dec->rel != REL_ARRAY) {
536 dec->rel = REL_ARRAY;
537 dec->array_max = "~0";/* unspecified size, use max */
538 }
539 }
540}
541
542static void
543get_type(prefixp, typep, dkind)
544 char **prefixp;
545 char **typep;
546 defkind dkind;
547{
548 token tok;
549
550 *prefixp = NULL((void *)0);
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
599static void
600unsigned_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}