missing_error_code: introduce new check
[smatch.git] / check_syscall_arg_type.c
blobdbabaae67918ab399ea21ec65a7b5917297e56ba
1 /*
2 * Copyright (C) 2017 Oracle.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
19 * This is to help create Trinity fuzzer templates.
23 #include "smatch.h"
24 #include "smatch_slist.h"
26 static int my_id;
28 STATE(ARG_FD);
29 #if 0
30 STATE(arg_range);
31 STATE(arg_op);
32 STATE(arg_list);
33 STATE(arg_cpu);
34 STATE(arg_pathname);
35 #endif
36 // nr_segs * sizeof(struct iovec)
37 // if (nr_segs > UIO_MAXIOV)
38 #if 0
39 STATE(arg_ioveclen);
40 STATE(arg_sockaddrlen);
41 STATE(arg_socketinfo);
42 #endif
44 struct smatch_state *merge_states(struct smatch_state *s1, struct smatch_state *s2)
46 if (s1 == &undefined)
47 return s2;
48 return s1;
51 struct typedef_lookup {
52 const char *name;
53 struct symbol *sym;
54 int failed;
57 static struct symbol *_typedef_lookup(const char *name)
59 struct ident *id;
60 struct symbol *node;
62 id = built_in_ident(name);
63 if (!id)
64 return NULL;
65 node = lookup_symbol(id, NS_TYPEDEF);
66 if (!node || node->type != SYM_NODE)
67 return NULL;
68 return get_real_base_type(node);
71 static void typedef_lookup(struct typedef_lookup *tl)
73 if (tl->sym || tl->failed)
74 return;
75 tl->sym = _typedef_lookup(tl->name);
76 if (!tl->sym)
77 tl->failed = 1;
80 static int is_mode_t(struct symbol *sym)
82 static struct typedef_lookup umode_t = { .name = "umode_t" };
83 struct symbol *type;
85 typedef_lookup(&umode_t);
86 if (!umode_t.sym)
87 return 0;
88 type = get_base_type(sym);
89 if (type == umode_t.sym)
90 return 1;
91 return 0;
94 static int is_pid_t(struct symbol *sym)
96 static struct typedef_lookup pid_t = { .name = "pid_t" };
97 struct symbol *type;
99 typedef_lookup(&pid_t);
100 if (!pid_t.sym)
101 return 0;
102 type = get_base_type(sym);
103 if (type == pid_t.sym)
104 return 1;
105 return 0;
108 static const char *get_arg_type_from_type(struct symbol *sym)
110 struct symbol *type;
112 if (is_mode_t(sym))
113 return "ARG_MODE_T";
114 if (is_pid_t(sym))
115 return "ARG_PID";
117 type = get_real_base_type(sym);
118 if (!type || type->type != SYM_PTR)
119 return NULL;
120 type = get_real_base_type(type);
121 if (!type)
122 return NULL;
123 if (type == &char_ctype)
124 return "ARG_MMAP";
125 if (!type->ident)
126 return NULL;
127 if (strcmp(type->ident->name, "iovec") == 0)
128 return "ARG_IOVEC";
129 if (strcmp(type->ident->name, "sockaddr") == 0)
130 return "ARG_SOCKADDR";
131 return "ARG_ADDRESS";
134 static void match_fdget(const char *fn, struct expression *expr, void *unused)
136 struct expression *arg;
138 arg = get_argument_from_call_expr(expr->args, 0);
139 set_state_expr(my_id, arg, &ARG_FD);
142 const char *get_syscall_arg_type(struct symbol *sym)
144 struct smatch_state *state;
145 const char *type;
147 if (!sym || !sym->ident)
148 return "ARG_UNDEFINED";
149 type = get_arg_type_from_type(sym);
150 if (type)
151 return type;
152 state = get_state(my_id, sym->ident->name, sym);
153 if (!state)
154 return "ARG_UNDEFINED";
155 return state->name;
158 void check_syscall_arg_type(int id)
160 my_id = id;
161 if (option_project != PROJ_KERNEL)
162 return;
164 set_dynamic_states(my_id);
165 add_merge_hook(my_id, &merge_states);
166 add_function_hook("fdget", &match_fdget, NULL);