39 state = __alloc_smatch_state(0);
40 state->name = alloc_sname(name);
41 state->data = sym;
42 return state;
43 }
44
45 static void undef(struct sm_state *sm, struct expression *mod_expr)
46 {
47 if (__in_fake_parameter_assign)
48 return;
49 set_state(my_id, sm->name, sm->sym, &undefined);
50 }
51
52 char *map_call_to_other_name_sym(const char *name, struct symbol *sym, struct symbol **new_sym)
53 {
54 struct smatch_state *state;
55 int skip;
56 char buf[256];
57
58 /* skip 'foo->'. This was checked in the caller. */
59 skip = strlen(sym->ident->name) + 2;
60
61 state = get_state(my_id, sym->ident->name, sym);
62 if (!state || !state->data)
63 return NULL;
64
65 snprintf(buf, sizeof(buf), "%s->%s", state->name, name + skip);
66 *new_sym = state->data;
67 return alloc_string(buf);
68 }
69
70 static char *map_my_state_long_to_short(struct sm_state *sm, const char *name, struct symbol *sym, struct symbol **new_sym, bool stack)
71 {
72 int len;
73 char buf[256];
74
75 if (sm->state->data != sym)
76 return NULL;
77 len = strlen(sm->state->name);
78 if (strncmp(name, sm->state->name, len) != 0)
79 return NULL;
80
81 if (name[len] == '.')
82 return NULL;
83 if (!stack && name[len] != '-')
84 return NULL;
85 snprintf(buf, sizeof(buf), "%s%s", sm->name, name + len);
86 *new_sym = sm->sym;
87 return alloc_string(buf);
88 }
89
90 static char *map_assignment_long_to_short(struct sm_state *sm, const char *name, struct symbol *sym, struct symbol **new_sym, bool stack)
91 {
92 struct expression *orig_expr;
93 struct symbol *orig_sym;
94 int len;
95 char buf[256];
96
97 orig_expr = sm->state->data;
98 if (!orig_expr)
99 return NULL;
100
101 /*
102 * Say we have an assignment like:
103 * foo->bar->my_ptr = my_ptr;
104 * We still expect the function to carry on using "my_ptr" as the
105 * shorter name. That's not a long to short mapping.
106 *
107 */
108 if (orig_expr->type == EXPR_SYMBOL)
109 return NULL;
110
111 orig_sym = expr_to_sym(orig_expr);
112 if (!orig_sym)
113 return NULL;
114 if (sym != orig_sym)
115 return NULL;
116
117 len = strlen(sm->state->name);
118 if (strncmp(name, sm->state->name, len) != 0)
119 return NULL;
120
121 if (name[len] == '.')
122 return NULL;
123 if (!stack && name[len] != '-')
124 return NULL;
125 snprintf(buf, sizeof(buf), "%s%s", sm->name, name + len);
126 *new_sym = sm->sym;
127 return alloc_string(buf);
128 }
129
130 /*
131 * Normally, we expect people to consistently refer to variables by the shortest
132 * name. So they use "b->a" instead of "foo->bar.a" when both point to the
133 * same memory location. However, when we're dealing across function boundaries
134 * then sometimes we pass frob(foo) which sets foo->bar.a. In that case, we
135 * translate it to the shorter name. Smatch extra updates the shorter name,
136 * which in turn updates the longer name.
137 *
138 */
139 static char *map_long_to_short_name_sym_helper(const char *name, struct symbol *sym, struct symbol **new_sym, bool stack)
140 {
141 char *ret;
142 struct sm_state *sm;
143
144 *new_sym = NULL;
145
146 FOR_EACH_SM(__get_cur_stree(), sm) {
147 if (sm->owner == my_id) {
148 ret = map_my_state_long_to_short(sm, name, sym, new_sym, stack);
149 if (ret)
150 return ret;
151 continue;
152 }
153 if (sm->owner == check_assigned_expr_id) {
154 ret = map_assignment_long_to_short(sm, name, sym, new_sym, stack);
155 if (ret)
156 return ret;
157 continue;
158 }
159 } END_FOR_EACH_SM(sm);
160
161 return NULL;
162 }
163
164 char *map_long_to_short_name_sym(const char *name, struct symbol *sym, struct symbol **new_sym)
165 {
166 return map_long_to_short_name_sym_helper(name, sym, new_sym, 1);
167 }
168
169 char *map_long_to_short_name_sym_nostack(const char *name, struct symbol *sym, struct symbol **new_sym)
170 {
171 return map_long_to_short_name_sym_helper(name, sym, new_sym, 0);
172 }
173
174 char *map_call_to_param_name_sym(struct expression *expr, struct symbol **sym)
175 {
176 char *name;
177 struct symbol *start_sym;
178 struct smatch_state *state;
179
180 *sym = NULL;
181
182 name = expr_to_str_sym(expr, &start_sym);
183 if (!name)
184 return NULL;
185 if (expr->type == EXPR_CALL)
186 start_sym = expr_to_sym(expr->fn);
187
188 state = get_state(my_id, name, start_sym);
189 free_string(name);
190 if (!state || !state->data)
191 return NULL;
192
193 *sym = state->data;
263 call = strip_expr(expr);
264 left_sym = expr_to_sym(call->fn);
265 if (!left_sym)
266 return;
267 left_name = expr_to_str(call);
268 if (!left_name)
269 return;
270
271 store_mapping_helper(left_name, left_sym, call, return_string);
272 goto free;
273
274 }
275
276 free:
277 free_string(left_name);
278 }
279
280 void register_return_to_param(int id)
281 {
282 my_id = id;
283 add_modification_hook(my_id, &undef);
284 }
285
286 void register_return_to_param_links(int id)
287 {
288 link_id = id;
289 set_up_link_functions(my_id, link_id);
290 }
291
|
39 state = __alloc_smatch_state(0);
40 state->name = alloc_sname(name);
41 state->data = sym;
42 return state;
43 }
44
45 static void undef(struct sm_state *sm, struct expression *mod_expr)
46 {
47 if (__in_fake_parameter_assign)
48 return;
49 set_state(my_id, sm->name, sm->sym, &undefined);
50 }
51
52 char *map_call_to_other_name_sym(const char *name, struct symbol *sym, struct symbol **new_sym)
53 {
54 struct smatch_state *state;
55 int skip;
56 char buf[256];
57
58 /* skip 'foo->'. This was checked in the caller. */
59 skip = sym->ident->len + 2;
60
61 state = get_state(my_id, sym->ident->name, sym);
62 if (!state || !state->data)
63 return NULL;
64
65 snprintf(buf, sizeof(buf), "%s->%s", state->name, name + skip);
66 *new_sym = state->data;
67 return alloc_string(buf);
68 }
69
70 static char *map_my_state_long_to_short(struct sm_state *sm, const char *name, struct symbol *sym, struct symbol **new_sym, bool stack)
71 {
72 int len;
73 char buf[256];
74
75 if (sm->state->data != sym)
76 return NULL;
77 len = strlen(sm->state->name);
78 if (strncmp(name, sm->state->name, len) != 0)
79 return NULL;
80
81 if (name[len] == '.')
82 return NULL;
83 if (!stack && name[len] != '-')
84 return NULL;
85 snprintf(buf, sizeof(buf), "%s%s", sm->name, name + len);
86 *new_sym = sm->sym;
87 return alloc_string(buf);
88 }
89
90 /*
91 * Normally, we expect people to consistently refer to variables by the shortest
92 * name. So they use "b->a" instead of "foo->bar.a" when both point to the
93 * same memory location. However, when we're dealing across function boundaries
94 * then sometimes we pass frob(foo) which sets foo->bar.a. In that case, we
95 * translate it to the shorter name. Smatch extra updates the shorter name,
96 * which in turn updates the longer name.
97 *
98 */
99 char *map_long_to_short_name_sym(const char *name, struct symbol *sym, struct symbol **new_sym, bool use_stack)
100 {
101 char *ret;
102 struct sm_state *sm;
103
104 *new_sym = NULL;
105
106 FOR_EACH_SM(__get_cur_stree(), sm) {
107 if (sm->owner == my_id) {
108 ret = map_my_state_long_to_short(sm, name, sym, new_sym, use_stack);
109 if (ret) {
110 if (local_debug)
111 sm_msg("%s: my_state: name = '%s' sm = '%s'",
112 __func__, name, show_sm(sm));
113 return ret;
114 }
115 continue;
116 }
117 } END_FOR_EACH_SM(sm);
118
119 return NULL;
120 }
121
122 char *map_call_to_param_name_sym(struct expression *expr, struct symbol **sym)
123 {
124 char *name;
125 struct symbol *start_sym;
126 struct smatch_state *state;
127
128 *sym = NULL;
129
130 name = expr_to_str_sym(expr, &start_sym);
131 if (!name)
132 return NULL;
133 if (expr->type == EXPR_CALL)
134 start_sym = expr_to_sym(expr->fn);
135
136 state = get_state(my_id, name, start_sym);
137 free_string(name);
138 if (!state || !state->data)
139 return NULL;
140
141 *sym = state->data;
211 call = strip_expr(expr);
212 left_sym = expr_to_sym(call->fn);
213 if (!left_sym)
214 return;
215 left_name = expr_to_str(call);
216 if (!left_name)
217 return;
218
219 store_mapping_helper(left_name, left_sym, call, return_string);
220 goto free;
221
222 }
223
224 free:
225 free_string(left_name);
226 }
227
228 void register_return_to_param(int id)
229 {
230 my_id = id;
231 set_dynamic_states(my_id);
232 add_modification_hook(my_id, &undef);
233 }
234
235 void register_return_to_param_links(int id)
236 {
237 link_id = id;
238 set_up_link_functions(my_id, link_id);
239 }
240
|