177 remove_from_equiv(name, sym);
178 set_union_info(name, sym, expr, state);
179 call_extra_mod_hooks(name, sym, expr, state);
180 update_mtag_data(expr, state);
181 if (in_param_set &&
182 estate_is_unknown(state) && !get_state(SMATCH_EXTRA, name, sym))
183 return;
184 set_state(SMATCH_EXTRA, name, sym, state);
185 }
186
187 static void set_extra_nomod_helper(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
188 {
189 call_extra_nomod_hooks(name, sym, expr, state);
190 set_state(SMATCH_EXTRA, name, sym, state);
191 }
192
193 static char *get_pointed_at(const char *name, struct symbol *sym, struct symbol **new_sym)
194 {
195 struct expression *assigned;
196
197 if (name[0] != '*')
198 return NULL;
199 if (strcmp(name + 1, sym->ident->name) != 0)
200 return NULL;
201
202 assigned = get_assigned_expr_name_sym(sym->ident->name, sym);
203 if (!assigned)
204 return NULL;
205 assigned = strip_parens(assigned);
206 if (assigned->type != EXPR_PREOP || assigned->op != '&')
207 return NULL;
208
209 return expr_to_var_sym(assigned->unop, new_sym);
210 }
211
212 char *get_other_name_sym_from_chunk(const char *name, const char *chunk, int len, struct symbol *sym, struct symbol **new_sym)
213 {
214 struct expression *assigned;
215 char *orig_name = NULL;
216 char buf[256];
237 if (!orig_name || !*new_sym)
238 goto free;
239
240 snprintf(buf, sizeof(buf), "%s->%s", orig_name, name + len);
241 ret = alloc_string(buf);
242 free_string(orig_name);
243 return ret;
244 free:
245 free_string(orig_name);
246 return NULL;
247 }
248
249 static char *get_long_name_sym(const char *name, struct symbol *sym, struct symbol **new_sym, bool use_stack)
250 {
251 struct expression *tmp;
252 struct sm_state *sm;
253 char buf[256];
254
255 /*
256 * Just prepend the name with a different name/sym and return that.
257 * For example, if we set "foo->bar = bar;" then we clamp "bar->baz",
258 * that also clamps "foo->bar->baz".
259 *
260 */
261
262 FOR_EACH_MY_SM(check_assigned_expr_id, __get_cur_stree(), sm) {
263 tmp = sm->state->data;
264 if (!tmp || tmp->type != EXPR_SYMBOL)
265 continue;
266 if (tmp->symbol == sym)
267 goto found;
268 } END_FOR_EACH_SM(sm);
269
270 return NULL;
271
272 found:
273 if (!use_stack && name[tmp->symbol->ident->len] != '-')
274 return NULL;
275 snprintf(buf, sizeof(buf), "%s%s", sm->name, name + tmp->symbol->ident->len);
276 *new_sym = sm->sym;
277 return alloc_string(buf);
278 }
279
280 char *get_other_name_sym_helper(const char *name, struct symbol *sym, struct symbol **new_sym, bool use_stack)
281 {
282 char buf[256];
283 char *ret;
284 int len;
285
286 *new_sym = NULL;
287
288 if (!sym || !sym->ident)
289 return NULL;
290
291 ret = get_pointed_at(name, sym, new_sym);
292 if (ret)
293 return ret;
294
295 ret = map_long_to_short_name_sym(name, sym, new_sym, use_stack);
1069 if (!name) {
1070 if (chunk_has_array(left))
1071 do_array_assign(left, '=', right);
1072 return;
1073 }
1074
1075 left_type = get_type(left);
1076 right_type = get_type(right);
1077
1078 right_name = expr_to_var_sym(right, &right_sym);
1079
1080 if (!__in_fake_assign &&
1081 !(right->type == EXPR_PREOP && right->op == '&') &&
1082 right_name && right_sym &&
1083 values_fit_type(left, strip_expr(right)) &&
1084 !has_symbol(right, sym)) {
1085 set_equiv(left, right);
1086 goto free;
1087 }
1088
1089 if (is_pointer(right) && get_address_rl(right, &rl)) {
1090 state = alloc_estate_rl(rl);
1091 goto done;
1092 }
1093
1094 if (get_implied_value(right, &sval)) {
1095 state = alloc_estate_sval(sval_cast(left_type, sval));
1096 goto done;
1097 }
1098
1099 if (__in_fake_assign) {
1100 struct smatch_state *right_state;
1101 sval_t sval;
1102
1103 if (get_value(right, &sval)) {
1104 sval = sval_cast(left_type, sval);
1105 state = alloc_estate_sval(sval);
1106 goto done;
1107 }
1108
1109 right_state = get_state(SMATCH_EXTRA, right_name, right_sym);
1110 if (right_state) {
1111 /* simple assignment */
1112 state = clone_estate(right_state);
1113 goto done;
|
177 remove_from_equiv(name, sym);
178 set_union_info(name, sym, expr, state);
179 call_extra_mod_hooks(name, sym, expr, state);
180 update_mtag_data(expr, state);
181 if (in_param_set &&
182 estate_is_unknown(state) && !get_state(SMATCH_EXTRA, name, sym))
183 return;
184 set_state(SMATCH_EXTRA, name, sym, state);
185 }
186
187 static void set_extra_nomod_helper(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
188 {
189 call_extra_nomod_hooks(name, sym, expr, state);
190 set_state(SMATCH_EXTRA, name, sym, state);
191 }
192
193 static char *get_pointed_at(const char *name, struct symbol *sym, struct symbol **new_sym)
194 {
195 struct expression *assigned;
196
197 /*
198 * Imagine we have an assignment: "foo = &addr;" then the other name
199 * of "*foo" is addr.
200 */
201
202 if (name[0] != '*')
203 return NULL;
204 if (strcmp(name + 1, sym->ident->name) != 0)
205 return NULL;
206
207 assigned = get_assigned_expr_name_sym(sym->ident->name, sym);
208 if (!assigned)
209 return NULL;
210 assigned = strip_parens(assigned);
211 if (assigned->type != EXPR_PREOP || assigned->op != '&')
212 return NULL;
213
214 return expr_to_var_sym(assigned->unop, new_sym);
215 }
216
217 char *get_other_name_sym_from_chunk(const char *name, const char *chunk, int len, struct symbol *sym, struct symbol **new_sym)
218 {
219 struct expression *assigned;
220 char *orig_name = NULL;
221 char buf[256];
242 if (!orig_name || !*new_sym)
243 goto free;
244
245 snprintf(buf, sizeof(buf), "%s->%s", orig_name, name + len);
246 ret = alloc_string(buf);
247 free_string(orig_name);
248 return ret;
249 free:
250 free_string(orig_name);
251 return NULL;
252 }
253
254 static char *get_long_name_sym(const char *name, struct symbol *sym, struct symbol **new_sym, bool use_stack)
255 {
256 struct expression *tmp;
257 struct sm_state *sm;
258 char buf[256];
259
260 /*
261 * Just prepend the name with a different name/sym and return that.
262 * For example, if we set "foo->bar = bar;" then the other name
263 * for "bar->baz" is "foo->bar->baz". Or if we have "foo = bar;" then
264 * the other name for "bar" is "foo". A third option is if we have
265 * "foo = bar;" then another name for "*bar" is "*foo".
266 */
267
268 FOR_EACH_MY_SM(check_assigned_expr_id, __get_cur_stree(), sm) {
269 tmp = sm->state->data;
270 if (!tmp || tmp->type != EXPR_SYMBOL)
271 continue;
272 if (tmp->symbol == sym)
273 goto found;
274 } END_FOR_EACH_SM(sm);
275
276 return NULL;
277
278 found:
279 if (!use_stack && name[tmp->symbol->ident->len] != '-')
280 return NULL;
281
282 if (name[0] == '*' && strcmp(name + 1, tmp->symbol_name->name) == 0)
283 snprintf(buf, sizeof(buf), "*%s", sm->name);
284 else if (name[tmp->symbol->ident->len] == '-' ||
285 name[tmp->symbol->ident->len] == '.')
286 snprintf(buf, sizeof(buf), "%s%s", sm->name, name + tmp->symbol->ident->len);
287 else if (strcmp(name, tmp->symbol_name->name) == 0)
288 snprintf(buf, sizeof(buf), "%s", sm->name);
289 else
290 return NULL;
291
292 *new_sym = sm->sym;
293 return alloc_string(buf);
294 }
295
296 char *get_other_name_sym_helper(const char *name, struct symbol *sym, struct symbol **new_sym, bool use_stack)
297 {
298 char buf[256];
299 char *ret;
300 int len;
301
302 *new_sym = NULL;
303
304 if (!sym || !sym->ident)
305 return NULL;
306
307 ret = get_pointed_at(name, sym, new_sym);
308 if (ret)
309 return ret;
310
311 ret = map_long_to_short_name_sym(name, sym, new_sym, use_stack);
1085 if (!name) {
1086 if (chunk_has_array(left))
1087 do_array_assign(left, '=', right);
1088 return;
1089 }
1090
1091 left_type = get_type(left);
1092 right_type = get_type(right);
1093
1094 right_name = expr_to_var_sym(right, &right_sym);
1095
1096 if (!__in_fake_assign &&
1097 !(right->type == EXPR_PREOP && right->op == '&') &&
1098 right_name && right_sym &&
1099 values_fit_type(left, strip_expr(right)) &&
1100 !has_symbol(right, sym)) {
1101 set_equiv(left, right);
1102 goto free;
1103 }
1104
1105 if (get_implied_value(right, &sval)) {
1106 state = alloc_estate_sval(sval_cast(left_type, sval));
1107 goto done;
1108 }
1109
1110 if (__in_fake_assign) {
1111 struct smatch_state *right_state;
1112 sval_t sval;
1113
1114 if (get_value(right, &sval)) {
1115 sval = sval_cast(left_type, sval);
1116 state = alloc_estate_sval(sval);
1117 goto done;
1118 }
1119
1120 right_state = get_state(SMATCH_EXTRA, right_name, right_sym);
1121 if (right_state) {
1122 /* simple assignment */
1123 state = clone_estate(right_state);
1124 goto done;
|