1 /*
2  * Copyright (C) 2008 Dan Carpenter.
3  *
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.
8  *
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.
13  *
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
16  *
17  * Copyright 2019 Joyent, Inc.
18  */
19 
20 /*
21  * Imagine we have this code:
22  * foo = 1;
23  * if (bar)
24  *         foo = 99;
25  * else
26  *         frob();
27  *                   //  <-- point #1
28  * if (foo == 99)    //  <-- point #2
29  *         bar->baz; //  <-- point #3
30  *
31  *
32  * At point #3 bar is non null and can be dereferenced.
33  *
34  * It's smatch_implied.c which sets bar to non null at point #2.
35  *
36  * At point #1 merge_slist() stores the list of states from both
37  * the true and false paths.  On the true path foo == 99 and on
38  * the false path foo == 1.  merge_slist() sets their pool
39  * list to show the other states which were there when foo == 99.
40  *
41  * When it comes to the if (foo == 99) the smatch implied hook
42  * looks for all the pools where foo was not 99.  It makes a list
43  * of those.
44  *
45  * Then for bar (and all the other states) it says, ok bar is a
46  * merged state that came from these previous states.  We'll
47  * chop out all the states where it came from a pool where
48  * foo != 99 and merge it all back together.
49  *
50  * That is the implied state of bar.
51  *
52  * merge_slist() sets up ->pool.  An sm_state only has one ->pool and
53  *    that is the pool where it was first set.  The my pool gets set when
54  *    code paths merge.  States that have been set since the last merge do
55  *    not have a ->pool.
56  * merge_sm_state() sets ->left and ->right.  (These are the states which were
57  *    merged to form the current state.)
58  * a pool:  a pool is an slist that has been merged with another slist.
59  */
60 
61 #include <sys/time.h>
62 #include <time.h>
63 #include "smatch.h"
64 #include "smatch_slist.h"
65 #include "smatch_extra.h"
66 
67 char *implied_debug_msg;
68 
69 bool implications_off;
70 
71 #define implied_debug 0
72 #define DIMPLIED(msg...) do { if (implied_debug) printf(msg); } while (0)
73 
74 /*
75  * tmp_range_list():
76  * It messes things up to free range list allocations.  This helper fuction
77  * lets us reuse memory instead of doing new allocations.
78  */
79 static struct range_list *tmp_range_list(struct symbol *type, long long num)
80 {
81 	static struct range_list *my_list = NULL;
82 	static struct data_range *my_range;
83 
84 	__free_ptr_list((struct ptr_list **)&my_list);
85 	my_range = alloc_range(ll_to_sval(num), ll_to_sval(num));
86 	add_ptr_list(&my_list, my_range);
87 	return my_list;
88 }
89 
90 static void print_debug_tf(struct sm_state *sm, int istrue, int isfalse)
91 {
92 	if (!implied_debug && !option_debug)
93 		return;
94 
95 	if (istrue && isfalse) {
96 		printf("%s: %d: does not exist.\n", show_sm(sm), sm->line);
97 	} else if (istrue) {
98 		printf("'%s = %s' from %d is true. %s[stree %d]\n", sm->name, show_state(sm->state),
99 			sm->line, sm->merged ? "[merged]" : "[leaf]",
100 			get_stree_id(sm->pool));
101 	} else if (isfalse) {
102 		printf("'%s = %s' from %d is false. %s[stree %d]\n", sm->name, show_state(sm->state),
103 			sm->line,
104 			sm->merged ? "[merged]" : "[leaf]",
105 			get_stree_id(sm->pool));
106 	} else {
107 		printf("'%s = %s' from %d could be true or false. %s[stree %d]\n", sm->name,
108 			show_state(sm->state), sm->line,
109 			sm->merged ? "[merged]" : "[leaf]",
110 			get_stree_id(sm->pool));
111 	}
112 }
113 
114 static int create_fake_history(struct sm_state *sm, int comparison, struct range_list *rl)
115 {
116 	struct range_list *orig_rl;
117 	struct range_list *true_rl, *false_rl;
118 	struct stree *true_stree, *false_stree;
119 	struct sm_state *true_sm, *false_sm;
120 	sval_t sval;
121 
122 	if (is_merged(sm) || sm->left || sm->right)
123 		return 0;
124 	if (!rl_to_sval(rl, &sval))
125 		return 0;
126 	if (!estate_rl(sm->state))
127 		return 0;
128 
129 	orig_rl = cast_rl(rl_type(rl), estate_rl(sm->state));
130 	split_comparison_rl(orig_rl, comparison, rl, &true_rl, &false_rl, NULL, NULL);
131 
132 	true_rl = rl_truncate_cast(estate_type(sm->state), true_rl);
133 	false_rl = rl_truncate_cast(estate_type(sm->state), false_rl);
134 	if (is_whole_rl(true_rl) || is_whole_rl(false_rl) ||
135 	    !true_rl || !false_rl ||
136 	    rl_equiv(orig_rl, true_rl) || rl_equiv(orig_rl, false_rl) ||
137 	    rl_equiv(estate_rl(sm->state), true_rl) || rl_equiv(estate_rl(sm->state), false_rl))
138 		return 0;
139 
140 	if (rl_intersection(true_rl, false_rl)) {
141 		sm_perror("parsing (%s (%s) %s %s)",
142 			sm->name, sm->state->name, show_special(comparison), show_rl(rl));
143 		sm_msg("true_rl = %s false_rl = %s intersection = %s",
144 		       show_rl(true_rl), show_rl(false_rl), show_rl(rl_intersection(true_rl, false_rl)));
145 		return 0;
146 	}
147 
148 	if (implied_debug)
149 		sm_msg("fake_history: %s vs %s.  %s %s %s. --> T: %s F: %s",
150 		       sm->name, show_rl(rl), sm->state->name, show_special(comparison), show_rl(rl),
151 		       show_rl(true_rl), show_rl(false_rl));
152 
153 	true_sm = clone_sm(sm);
154 	false_sm = clone_sm(sm);
155 
156 	true_sm->state = clone_partial_estate(sm->state, true_rl);
157 	free_slist(&true_sm->possible);
158 	add_possible_sm(true_sm, true_sm);
159 	false_sm->state = clone_partial_estate(sm->state, false_rl);
160 	free_slist(&false_sm->possible);
161 	add_possible_sm(false_sm, false_sm);
162 
163 	true_stree = clone_stree(sm->pool);
164 	false_stree = clone_stree(sm->pool);
165 
166 	overwrite_sm_state_stree(&true_stree, true_sm);
167 	overwrite_sm_state_stree(&false_stree, false_sm);
168 
169 	true_sm->pool = true_stree;
170 	false_sm->pool = false_stree;
171 
172 	sm->merged = 1;
173 	sm->left = true_sm;
174 	sm->right = false_sm;
175 
176 	return 1;
177 }
178 
179 /*
180  * add_pool() adds a slist to *pools. If the slist has already been
181  * added earlier then it doesn't get added a second time.
182  */
183 void add_pool(struct state_list **pools, struct sm_state *new)
184 {
185 	struct sm_state *tmp;
186 
187 	FOR_EACH_PTR(*pools, tmp) {
188 		if (tmp->pool < new->pool)
189 			continue;
190 		else if (tmp->pool == new->pool) {
191 			return;
192 		} else {
193 			INSERT_CURRENT(new, tmp);
194 			return;
195 		}
196 	} END_FOR_EACH_PTR(tmp);
197 	add_ptr_list(pools, new);
198 }
199 
200 static int pool_in_pools(struct stree *pool,
201 			 const struct state_list *slist)
202 {
203 	struct sm_state *tmp;
204 
205 	FOR_EACH_PTR(slist, tmp) {
206 		if (!tmp->pool)
207 			continue;
208 		if (tmp->pool == pool)
209 			return 1;
210 	} END_FOR_EACH_PTR(tmp);
211 	return 0;
212 }
213 
214 static int remove_pool(struct state_list **pools, struct stree *remove)
215 {
216 	struct sm_state *tmp;
217 	int ret = 0;
218 
219 	FOR_EACH_PTR(*pools, tmp) {
220 		if (tmp->pool == remove) {
221 			DELETE_CURRENT_PTR(tmp);
222 			ret = 1;
223 		}
224 	} END_FOR_EACH_PTR(tmp);
225 
226 	return ret;
227 }
228 
229 /*
230  * If 'foo' == 99 add it that pool to the true pools.  If it's false, add it to
231  * the false pools.  If we're not sure, then we don't add it to either.
232  */
233 static void do_compare(struct sm_state *sm, int comparison, struct range_list *rl,
234 			struct state_list **true_stack,
235 			struct state_list **maybe_stack,
236 			struct state_list **false_stack,
237 			int *mixed, struct sm_state *gate_sm)
238 {
239 	int istrue;
240 	int isfalse;
241 	struct range_list *var_rl;
242 
243 	if (!sm->pool)
244 		return;
245 
246 	var_rl = cast_rl(rl_type(rl), estate_rl(sm->state));
247 
248 	istrue = !possibly_false_rl(var_rl, comparison, rl);
249 	isfalse = !possibly_true_rl(var_rl, comparison, rl);
250 
251 	print_debug_tf(sm, istrue, isfalse);
252 
253 	/* give up if we have borrowed implications (smatch_equiv.c) */
254 	if (sm->sym != gate_sm->sym ||
255 	    strcmp(sm->name, gate_sm->name) != 0) {
256 		if (mixed)
257 			*mixed = 1;
258 	}
259 
260 	if (mixed && !*mixed && !is_merged(sm) && !istrue && !isfalse) {
261 		if (!create_fake_history(sm, comparison, rl))
262 			*mixed = 1;
263 	}
264 
265 	if (istrue)
266 		add_pool(true_stack, sm);
267 	else if (isfalse)
268 		add_pool(false_stack, sm);
269 	else
270 		add_pool(maybe_stack, sm);
271 }
272 
273 static int is_checked(struct state_list *checked, struct sm_state *sm)
274 {
275 	struct sm_state *tmp;
276 
277 	FOR_EACH_PTR(checked, tmp) {
278 		if (tmp == sm)
279 			return 1;
280 	} END_FOR_EACH_PTR(tmp);
281 	return 0;
282 }
283 
284 /*
285  * separate_pools():
286  * Example code:  if (foo == 99) {
287  *
288  * Say 'foo' is a merged state that has many possible values.  It is the combination
289  * of merges.  separate_pools() iterates through the pools recursively and calls
290  * do_compare() for each time 'foo' was set.
291  */
292 static void __separate_pools(struct sm_state *sm, int comparison, struct range_list *rl,
293 			struct state_list **true_stack,
294 			struct state_list **maybe_stack,
295 			struct state_list **false_stack,
296 			struct state_list **checked, int *mixed, struct sm_state *gate_sm,
297 			struct timeval *start_time)
298 {
299 	int free_checked = 0;
300 	struct state_list *checked_states = NULL;
301 	struct timeval now;
302 
303 	if (!sm)
304 		return;
305 
306 	gettimeofday(&now, NULL);
307 	if (now.tv_usec - start_time->tv_usec > 1000000) {
308 		if (implied_debug) {
309 			sm_msg("debug: %s: implications taking too long.  (%s %s %s)",
310 			       __func__, sm->state->name, show_special(comparison), show_rl(rl));
311 		}
312 		if (mixed)
313 			*mixed = 1;
314 	}
315 
316 	if (checked == NULL) {
317 		checked = &checked_states;
318 		free_checked = 1;
319 	}
320 	if (is_checked(*checked, sm))
321 		return;
322 	add_ptr_list(checked, sm);
323 
324 	do_compare(sm, comparison, rl, true_stack, maybe_stack, false_stack, mixed, gate_sm);
325 
326 	__separate_pools(sm->left, comparison, rl, true_stack, maybe_stack, false_stack, checked, mixed, gate_sm, start_time);
327 	__separate_pools(sm->right, comparison, rl, true_stack, maybe_stack, false_stack, checked, mixed, gate_sm, start_time);
328 	if (free_checked)
329 		free_slist(checked);
330 }
331 
332 static void separate_pools(struct sm_state *sm, int comparison, struct range_list *rl,
333 			struct state_list **true_stack,
334 			struct state_list **false_stack,
335 			struct state_list **checked, int *mixed)
336 {
337 	struct state_list *maybe_stack = NULL;
338 	struct sm_state *tmp;
339 	struct timeval start_time;
340 
341 
342 	gettimeofday(&start_time, NULL);
343 	__separate_pools(sm, comparison, rl, true_stack, &maybe_stack, false_stack, checked, mixed, sm, &start_time);
344 
345 	if (implied_debug) {
346 		struct sm_state *sm;
347 
348 		FOR_EACH_PTR(*true_stack, sm) {
349 			sm_msg("TRUE %s [stree %d]", show_sm(sm), get_stree_id(sm->pool));
350 		} END_FOR_EACH_PTR(sm);
351 
352 		FOR_EACH_PTR(maybe_stack, sm) {
353 			sm_msg("MAYBE %s %s[stree %d]",
354 			       show_sm(sm), sm->merged ? "(merged) ": "", get_stree_id(sm->pool));
355 		} END_FOR_EACH_PTR(sm);
356 
357 		FOR_EACH_PTR(*false_stack, sm) {
358 			sm_msg("FALSE %s [stree %d]", show_sm(sm), get_stree_id(sm->pool));
359 		} END_FOR_EACH_PTR(sm);
360 	}
361 	/* if it's a maybe then remove it */
362 	FOR_EACH_PTR(maybe_stack, tmp) {
363 		remove_pool(false_stack, tmp->pool);
364 		remove_pool(true_stack, tmp->pool);
365 	} END_FOR_EACH_PTR(tmp);
366 
367 	/* if it's both true and false remove it from both */
368 	FOR_EACH_PTR(*true_stack, tmp) {
369 		if (remove_pool(false_stack, tmp->pool))
370 			DELETE_CURRENT_PTR(tmp);
371 	} END_FOR_EACH_PTR(tmp);
372 }
373 
374 static int sm_in_keep_leafs(struct sm_state *sm, const struct state_list *keep_gates)
375 {
376 	struct sm_state *tmp, *old;
377 
378 	FOR_EACH_PTR(keep_gates, tmp) {
379 		if (is_merged(tmp))
380 			continue;
381 		old = get_sm_state_stree(tmp->pool, sm->owner, sm->name, sm->sym);
382 		if (!old)
383 			continue;
384 		if (old == sm)
385 			return 1;
386 	} END_FOR_EACH_PTR(tmp);
387 	return 0;
388 }
389 
390 static int going_too_slow(void)
391 {
392 	static void *printed;
393 
394 	if (out_of_memory()) {
395 		implications_off = true;
396 		return 1;
397 	}
398 
399 	if (!option_timeout || time_parsing_function() < option_timeout) {
400 		implications_off = false;
401 		return 0;
402 	}
403 
404 	if (!__inline_fn && printed != cur_func_sym) {
405 		if (!is_skipped_function())
406 			sm_perror("turning off implications after %d seconds", option_timeout);
407 		printed = cur_func_sym;
408 	}
409 	implications_off = true;
410 	return 1;
411 }
412 
413 static char *sm_state_info(struct sm_state *sm)
414 {
415 	static char buf[512];
416 	int n = 0;
417 
418 	n += snprintf(buf + n, sizeof(buf) - n, "[stree %d line %d] ",
419 		      get_stree_id(sm->pool),  sm->line);
420 	if (n >= sizeof(buf))
421 		return buf;
422 	n += snprintf(buf + n, sizeof(buf) - n, "%s ", show_sm(sm));
423 	if (n >= sizeof(buf))
424 		return buf;
425 	n += snprintf(buf + n, sizeof(buf) - n, "left = %s [stree %d] ",
426 		      sm->left ? sm->left->state->name : "<none>",
427 		      sm->left ? get_stree_id(sm->left->pool) : -1);
428 	if (n >= sizeof(buf))
429 		return buf;
430 	n += snprintf(buf + n, sizeof(buf) - n, "right = %s [stree %d]",
431 		      sm->right ? sm->right->state->name : "<none>",
432 		      sm->right ? get_stree_id(sm->right->pool) : -1);
433 	return buf;
434 }
435 
436 /*
437  * NOTE: If a state is in both the keep stack and the remove stack then that is
438  * a bug.  Only add states which are definitely true or definitely false.  If
439  * you have a leaf state that could be both true and false, then create a fake
440  * split history where one side is true and one side is false.  Otherwise, if
441  * you can't do that, then don't add it to either list.
442  */
443 #define RECURSE_LIMIT 300
444 struct sm_state *filter_pools(struct sm_state *sm,
445 			      const struct state_list *remove_stack,
446 			      const struct state_list *keep_stack,
447 			      int *modified, int *recurse_cnt,
448 			      struct timeval *start, int *skip, int *bail)
449 {
450 	struct sm_state *ret = NULL;
451 	struct sm_state *left;
452 	struct sm_state *right;
453 	int removed = 0;
454 	struct timeval now;
455 
456 	if (!sm)
457 		return NULL;
458 	if (*bail)
459 		return NULL;
460 	gettimeofday(&now, NULL);
461 	if (now.tv_usec - start->tv_usec > 3000000) {
462 		DIMPLIED("%s: implications taking too long: %s\n", __func__, sm_state_info(sm));
463 		*bail = 1;
464 		return NULL;
465 	}
466 	if ((*recurse_cnt)++ > RECURSE_LIMIT) {
467 		DIMPLIED("%s: recursed too far:  %s\n", __func__, sm_state_info(sm));
468 		*skip = 1;
469 		return NULL;
470 	}
471 
472 	if (pool_in_pools(sm->pool, remove_stack)) {
473 		DIMPLIED("%s: remove: %s\n", __func__, sm_state_info(sm));
474 		*modified = 1;
475 		return NULL;
476 	}
477 
478 	if (!is_merged(sm) || pool_in_pools(sm->pool, keep_stack) || sm_in_keep_leafs(sm, keep_stack)) {
479 		DIMPLIED("%s: keep %s (%s, %s, %s): %s\n", __func__, sm->state->name,
480 			is_merged(sm) ? "merged" : "not merged",
481 			pool_in_pools(sm->pool, keep_stack) ? "not in keep pools" : "in keep pools",
482 			sm_in_keep_leafs(sm, keep_stack) ? "reachable keep leaf" : "no keep leaf",
483 			sm_state_info(sm));
484 		return sm;
485 	}
486 
487 	left = filter_pools(sm->left, remove_stack, keep_stack, &removed, recurse_cnt, start, skip, bail);
488 	right = filter_pools(sm->right, remove_stack, keep_stack, &removed, recurse_cnt, start, skip, bail);
489 	if (*bail || *skip)
490 		return NULL;
491 	if (!removed) {
492 		DIMPLIED("%s: kept all: %s\n", __func__, sm_state_info(sm));
493 		return sm;
494 	}
495 	*modified = 1;
496 	if (!left && !right) {
497 		DIMPLIED("%s: removed all: %s\n", __func__, sm_state_info(sm));
498 		return NULL;
499 	}
500 
501 	if (!left) {
502 		ret = clone_sm(right);
503 		ret->merged = 1;
504 		ret->right = right;
505 		ret->left = NULL;
506 	} else if (!right) {
507 		ret = clone_sm(left);
508 		ret->merged = 1;
509 		ret->left = left;
510 		ret->right = NULL;
511 	} else {
512 		if (left->sym != sm->sym || strcmp(left->name, sm->name) != 0) {
513 			left = clone_sm(left);
514 			left->sym = sm->sym;
515 			left->name = sm->name;
516 		}
517 		if (right->sym != sm->sym || strcmp(right->name, sm->name) != 0) {
518 			right = clone_sm(right);
519 			right->sym = sm->sym;
520 			right->name = sm->name;
521 		}
522 		ret = merge_sm_states(left, right);
523 	}
524 
525 	ret->pool = sm->pool;
526 
527 	DIMPLIED("%s: partial: %s\n", __func__, sm_state_info(sm));
528 	return ret;
529 }
530 
531 static struct stree *filter_stack(struct sm_state *gate_sm,
532 				       struct stree *pre_stree,
533 				       const struct state_list *remove_stack,
534 				       const struct state_list *keep_stack)
535 {
536 	struct stree *ret = NULL;
537 	struct sm_state *tmp;
538 	struct sm_state *filtered_sm;
539 	int modified;
540 	int recurse_cnt;
541 	struct timeval start;
542 	int skip;
543 	int bail = 0;
544 
545 	if (!remove_stack)
546 		return NULL;
547 
548 	gettimeofday(&start, NULL);
549 	FOR_EACH_SM(pre_stree, tmp) {
550 		if (!tmp->merged || sm_in_keep_leafs(tmp, keep_stack))
551 			continue;
552 		modified = 0;
553 		recurse_cnt = 0;
554 		skip = 0;
555 		filtered_sm = filter_pools(tmp, remove_stack, keep_stack, &modified, &recurse_cnt, &start, &skip, &bail);
556 		if (going_too_slow())
557 			return NULL;
558 		if (bail)
559 			return ret;  /* Return the implications we figured out before time ran out. */
560 
561 
562 		if (skip || !filtered_sm || !modified)
563 			continue;
564 		/* the assignments here are for borrowed implications */
565 		filtered_sm->name = tmp->name;
566 		filtered_sm->sym = tmp->sym;
567 		avl_insert(&ret, filtered_sm);
568 	} END_FOR_EACH_SM(tmp);
569 	return ret;
570 }
571 
572 static void separate_and_filter(struct sm_state *sm, int comparison, struct range_list *rl,
573 		struct stree *pre_stree,
574 		struct stree **true_states,
575 		struct stree **false_states,
576 		int *mixed)
577 {
578 	struct state_list *true_stack = NULL;
579 	struct state_list *false_stack = NULL;
580 	struct timeval time_before;
581 	struct timeval time_after;
582 	int sec;
583 
584 	gettimeofday(&time_before, NULL);
585 
586 	DIMPLIED("checking implications: (%s (%s) %s %s)\n",
587 		 sm->name, sm->state->name, show_special(comparison), show_rl(rl));
588 
589 	if (!is_merged(sm)) {
590 		DIMPLIED("%d '%s' from line %d is not merged.\n", get_lineno(), sm->name, sm->line);
591 		return;
592 	}
593 
594 	separate_pools(sm, comparison, rl, &true_stack, &false_stack, NULL, mixed);
595 
596 	DIMPLIED("filtering true stack.\n");
597 	*true_states = filter_stack(sm, pre_stree, false_stack, true_stack);
598 	DIMPLIED("filtering false stack.\n");
599 	*false_states = filter_stack(sm, pre_stree, true_stack, false_stack);
600 	free_slist(&true_stack);
601 	free_slist(&false_stack);
602 	if (implied_debug) {
603 		printf("These are the implied states for the true path: (%s (%s) %s %s)\n",
604 		       sm->name, sm->state->name, show_special(comparison), show_rl(rl));
605 		__print_stree(*true_states);
606 		printf("These are the implied states for the false path: (%s (%s) %s %s)\n",
607 		       sm->name, sm->state->name, show_special(comparison), show_rl(rl));
608 		__print_stree(*false_states);
609 	}
610 
611 	gettimeofday(&time_after, NULL);
612 	sec = time_after.tv_sec - time_before.tv_sec;
613 	if (option_timeout && sec > option_timeout) {
614 		sm_perror("Function too hairy.  Ignoring implications after %d seconds.", sec);
615 	}
616 }
617 
618 static struct expression *get_last_expr(struct statement *stmt)
619 {
620 	struct statement *last;
621 
622 	last = last_ptr_list((struct ptr_list *)stmt->stmts);
623 	if (last->type == STMT_EXPRESSION)
624 		return last->expression;
625 
626 	if (last->type == STMT_LABEL) {
627 		if (last->label_statement &&
628 		    last->label_statement->type == STMT_EXPRESSION)
629 			return last->label_statement->expression;
630 	}
631 
632 	return NULL;
633 }
634 
635 static struct expression *get_left_most_expr(struct expression *expr)
636 {
637 	struct statement *compound;
638 
639 	compound = get_expression_statement(expr);
640 	if (compound)
641 		return get_last_expr(compound);
642 
643 	expr = strip_parens(expr);
644 	if (expr->type == EXPR_ASSIGNMENT)
645 		return get_left_most_expr(expr->left);
646 	return expr;
647 }
648 
649 static int is_merged_expr(struct expression  *expr)
650 {
651 	struct sm_state *sm;
652 	sval_t dummy;
653 
654 	if (get_value(expr, &dummy))
655 		return 0;
656 	sm = get_sm_state_expr(SMATCH_EXTRA, expr);
657 	if (!sm)
658 		return 0;
659 	if (is_merged(sm))
660 		return 1;
661 	return 0;
662 }
663 
664 static void delete_gate_sm_equiv(struct stree **stree, const char *name, struct symbol *sym)
665 {
666 	struct smatch_state *state;
667 	struct relation *rel;
668 
669 	state = get_state(SMATCH_EXTRA, name, sym);
670 	if (!state)
671 		return;
672 	FOR_EACH_PTR(estate_related(state), rel) {
673 		delete_state_stree(stree, SMATCH_EXTRA, rel->name, rel->sym);
674 	} END_FOR_EACH_PTR(rel);
675 }
676 
677 static void delete_gate_sm(struct stree **stree, const char *name, struct symbol *sym)
678 {
679 	delete_state_stree(stree, SMATCH_EXTRA, name, sym);
680 }
681 
682 static int handle_comparison(struct expression *expr,
683 			      struct stree **implied_true,
684 			      struct stree **implied_false)
685 {
686 	struct sm_state *sm = NULL;
687 	struct range_list *rl = NULL;
688 	struct expression *left;
689 	struct expression *right;
690 	struct symbol *type;
691 	int comparison = expr->op;
692 	int mixed = 0;
693 
694 	left = get_left_most_expr(expr->left);
695 	right = get_left_most_expr(expr->right);
696 
697 	if (is_merged_expr(left)) {
698 		sm = get_sm_state_expr(SMATCH_EXTRA, left);
699 		get_implied_rl(right, &rl);
700 	} else if (is_merged_expr(right)) {
701 		sm = get_sm_state_expr(SMATCH_EXTRA, right);
702 		get_implied_rl(left, &rl);
703 		comparison = flip_comparison(comparison);
704 	}
705 
706 	if (!rl || !sm)
707 		return 0;
708 
709 	type = get_type(expr);
710 	if (!type)
711 		return 0;
712 	if (type_positive_bits(rl_type(rl)) > type_positive_bits(type))
713 		type = rl_type(rl);
714 	if (type_positive_bits(type) < 31)
715 		type = &int_ctype;
716 	rl = cast_rl(type, rl);
717 
718 	separate_and_filter(sm, comparison, rl, __get_cur_stree(), implied_true, implied_false, &mixed);
719 
720 	delete_gate_sm_equiv(implied_true, sm->name, sm->sym);
721 	delete_gate_sm_equiv(implied_false, sm->name, sm->sym);
722 	if (mixed) {
723 		delete_gate_sm(implied_true, sm->name, sm->sym);
724 		delete_gate_sm(implied_false, sm->name, sm->sym);
725 	}
726 
727 	return 1;
728 }
729 
730 static int handle_zero_comparison(struct expression *expr,
731 				struct stree **implied_true,
732 				struct stree **implied_false)
733 {
734 	struct symbol *sym;
735 	char *name;
736 	struct sm_state *sm;
737 	int mixed = 0;
738 	int ret = 0;
739 
740 	if (expr->type == EXPR_POSTOP)
741 		expr = strip_expr(expr->unop);
742 
743 	if (expr->type == EXPR_ASSIGNMENT) {
744 		/* most of the time ->pools will be empty here because we
745 		   just set the state, but if have assigned a conditional
746 		   function there are implications. */
747 		expr = expr->left;
748 	}
749 
750 	name = expr_to_var_sym(expr, &sym);
751 	if (!name || !sym)
752 		goto free;
753 	sm = get_sm_state(SMATCH_EXTRA, name, sym);
754 	if (!sm)
755 		goto free;
756 
757 	separate_and_filter(sm, SPECIAL_NOTEQUAL, tmp_range_list(estate_type(sm->state), 0), __get_cur_stree(), implied_true, implied_false, &mixed);
758 	delete_gate_sm_equiv(implied_true, sm->name, sm->sym);
759 	delete_gate_sm_equiv(implied_false, sm->name, sm->sym);
760 	if (mixed) {
761 		delete_gate_sm(implied_true, sm->name, sm->sym);
762 		delete_gate_sm(implied_false, sm->name, sm->sym);
763 	}
764 
765 	ret = 1;
766 free:
767 	free_string(name);
768 	return ret;
769 }
770 
771 static int handled_by_comparison_hook(struct expression *expr,
772 				   struct stree **implied_true,
773 				   struct stree **implied_false)
774 {
775 	struct state_list *true_stack = NULL;
776 	struct state_list *false_stack = NULL;
777 	struct stree *pre_stree;
778 	struct sm_state *sm;
779 
780 	sm = comparison_implication_hook(expr, &true_stack, &false_stack);
781 	if (!sm)
782 		return 0;
783 
784 	pre_stree = clone_stree(__get_cur_stree());
785 
786 	*implied_true = filter_stack(sm, pre_stree, false_stack, true_stack);
787 	*implied_false = filter_stack(sm, pre_stree, true_stack, false_stack);
788 
789 	free_stree(&pre_stree);
790 	free_slist(&true_stack);
791 	free_slist(&false_stack);
792 
793 	return 1;
794 }
795 
796 static int handled_by_extra_states(struct expression *expr,
797 				   struct stree **implied_true,
798 				   struct stree **implied_false)
799 {
800 	if (expr->type == EXPR_COMPARE)
801 		return handle_comparison(expr, implied_true, implied_false);
802 	else
803 		return handle_zero_comparison(expr, implied_true, implied_false);
804 }
805 
806 static int handled_by_stored_conditions(struct expression *expr,
807 					struct stree **implied_true,
808 					struct stree **implied_false)
809 {
810 	struct state_list *true_stack = NULL;
811 	struct state_list *false_stack = NULL;
812 	struct stree *pre_stree;
813 	struct sm_state *sm;
814 
815 	sm = stored_condition_implication_hook(expr, &true_stack, &false_stack);
816 	if (!sm)
817 		return 0;
818 
819 	pre_stree = clone_stree(__get_cur_stree());
820 
821 	*implied_true = filter_stack(sm, pre_stree, false_stack, true_stack);
822 	*implied_false = filter_stack(sm, pre_stree, true_stack, false_stack);
823 
824 	free_stree(&pre_stree);
825 	free_slist(&true_stack);
826 	free_slist(&false_stack);
827 
828 	return 1;
829 }
830 
831 static struct stree *saved_implied_true;
832 static struct stree *saved_implied_false;
833 static struct stree *extra_saved_implied_true;
834 static struct stree *extra_saved_implied_false;
835 
836 static void separate_extra_states(struct stree **implied_true,
837 				  struct stree **implied_false)
838 {
839 	struct sm_state *sm;
840 
841 	/* We process extra states later to preserve the implications. */
842 	FOR_EACH_SM(*implied_true, sm) {
843 		if (sm->owner == SMATCH_EXTRA)
844 			overwrite_sm_state_stree(&extra_saved_implied_true, sm);
845 	} END_FOR_EACH_SM(sm);
846 	FOR_EACH_SM(extra_saved_implied_true, sm) {
847 		delete_state_stree(implied_true, sm->owner, sm->name, sm->sym);
848 	} END_FOR_EACH_SM(sm);
849 
850 	FOR_EACH_SM(*implied_false, sm) {
851 		if (sm->owner == SMATCH_EXTRA)
852 			overwrite_sm_state_stree(&extra_saved_implied_false, sm);
853 	} END_FOR_EACH_SM(sm);
854 	FOR_EACH_SM(extra_saved_implied_false, sm) {
855 		delete_state_stree(implied_false, sm->owner, sm->name, sm->sym);
856 	} END_FOR_EACH_SM(sm);
857 }
858 
859 static void get_tf_states(struct expression *expr,
860 			  struct stree **implied_true,
861 			  struct stree **implied_false)
862 {
863 	if (handled_by_comparison_hook(expr, implied_true, implied_false))
864 		return;
865 
866 	if (handled_by_extra_states(expr, implied_true, implied_false)) {
867 		separate_extra_states(implied_true, implied_false);
868 		return;
869 	}
870 
871 	if (handled_by_stored_conditions(expr, implied_true, implied_false))
872 		return;
873 }
874 
875 static void save_implications_hook(struct expression *expr)
876 {
877 	if (going_too_slow())
878 		return;
879 	get_tf_states(expr, &saved_implied_true, &saved_implied_false);
880 }
881 
882 static void set_implied_states(struct expression *expr)
883 {
884 	struct sm_state *sm;
885 
886 	FOR_EACH_SM(saved_implied_true, sm) {
887 		__set_true_false_sm(sm, NULL);
888 	} END_FOR_EACH_SM(sm);
889 	free_stree(&saved_implied_true);
890 
891 	FOR_EACH_SM(saved_implied_false, sm) {
892 		__set_true_false_sm(NULL, sm);
893 	} END_FOR_EACH_SM(sm);
894 	free_stree(&saved_implied_false);
895 }
896 
897 static void set_extra_implied_states(struct expression *expr)
898 {
899 	saved_implied_true = extra_saved_implied_true;
900 	saved_implied_false = extra_saved_implied_false;
901 	extra_saved_implied_true = NULL;
902 	extra_saved_implied_false = NULL;
903 	set_implied_states(NULL);
904 }
905 
906 void param_limit_implications(struct expression *expr, int param, char *key, char *value)
907 {
908 	struct expression *arg;
909 	struct symbol *compare_type;
910 	char *name;
911 	struct symbol *sym;
912 	struct sm_state *sm;
913 	struct sm_state *tmp;
914 	struct stree *implied_true = NULL;
915 	struct stree *implied_false = NULL;
916 	struct range_list *orig, *limit;
917 
918 	if (time_parsing_function() > 40)
919 		return;
920 
921 	while (expr->type == EXPR_ASSIGNMENT)
922 		expr = strip_expr(expr->right);
923 	if (expr->type != EXPR_CALL)
924 		return;
925 
926 	arg = get_argument_from_call_expr(expr->args, param);
927 	if (!arg)
928 		return;
929 
930 	arg = strip_parens(arg);
931 	while (arg->type == EXPR_ASSIGNMENT && arg->op == '=')
932 		arg = strip_parens(arg->left);
933 
934 	name = get_variable_from_key(arg, key, &sym);
935 	if (!name || !sym)
936 		goto free;
937 
938 	sm = get_sm_state(SMATCH_EXTRA, name, sym);
939 	if (!sm || !sm->merged)
940 		goto free;
941 
942 	if (strcmp(key, "$") == 0)
943 		compare_type = get_arg_type(expr->fn, param);
944 	else
945 		compare_type = get_member_type_from_key(arg, key);
946 
947 	orig = estate_rl(sm->state);
948 	orig = cast_rl(compare_type, orig);
949 
950 	call_results_to_rl(expr, compare_type, value, &limit);
951 
952 	separate_and_filter(sm, SPECIAL_EQUAL, limit, __get_cur_stree(), &implied_true, &implied_false, NULL);
953 
954 	FOR_EACH_SM(implied_true, tmp) {
955 		__set_sm_fake_stree(tmp);
956 	} END_FOR_EACH_SM(tmp);
957 
958 	free_stree(&implied_true);
959 	free_stree(&implied_false);
960 free:
961 	free_string(name);
962 }
963 
964 struct stree *__implied_case_stree(struct expression *switch_expr,
965 				   struct range_list *rl,
966 				   struct range_list_stack **remaining_cases,
967 				   struct stree **raw_stree)
968 {
969 	char *name;
970 	struct symbol *sym;
971 	struct var_sym_list *vsl;
972 	struct sm_state *sm;
973 	struct stree *true_states = NULL;
974 	struct stree *false_states = NULL;
975 	struct stree *extra_states;
976 	struct stree *ret = clone_stree(*raw_stree);
977 
978 	name = expr_to_chunk_sym_vsl(switch_expr, &sym, &vsl);
979 
980 	if (rl)
981 		filter_top_rl(remaining_cases, rl);
982 	else
983 		rl = clone_rl(top_rl(*remaining_cases));
984 
985 	if (name) {
986 		sm = get_sm_state_stree(*raw_stree, SMATCH_EXTRA, name, sym);
987 		if (sm)
988 			separate_and_filter(sm, SPECIAL_EQUAL, rl, *raw_stree, &true_states, &false_states, NULL);
989 	}
990 
991 	__push_fake_cur_stree();
992 	__unnullify_path();
993 	if (name)
994 		set_extra_nomod_vsl(name, sym, vsl, NULL, alloc_estate_rl(rl));
995 	__pass_case_to_client(switch_expr, rl);
996 	extra_states = __pop_fake_cur_stree();
997 	overwrite_stree(extra_states, &true_states);
998 	overwrite_stree(true_states, &ret);
999 	free_stree(&extra_states);
1000 	free_stree(&true_states);
1001 	free_stree(&false_states);
1002 
1003 	free_string(name);
1004 	return ret;
1005 }
1006 
1007 static void match_end_func(struct symbol *sym)
1008 {
1009 	if (__inline_fn)
1010 		return;
1011 	implied_debug_msg = NULL;
1012 }
1013 
1014 static void get_tf_stacks_from_pool(struct sm_state *gate_sm,
1015 				    struct sm_state *pool_sm,
1016 				    struct state_list **true_stack,
1017 				    struct state_list **false_stack)
1018 {
1019 	struct sm_state *tmp;
1020 	int possibly_true = 0;
1021 
1022 	if (!gate_sm)
1023 		return;
1024 
1025 	if (strcmp(gate_sm->state->name, pool_sm->state->name) == 0) {
1026 		add_ptr_list(true_stack, pool_sm);
1027 		return;
1028 	}
1029 
1030 	FOR_EACH_PTR(gate_sm->possible, tmp) {
1031 		if (strcmp(tmp->state->name, pool_sm->state->name) == 0) {
1032 			possibly_true = 1;
1033 			break;
1034 		}
1035 	} END_FOR_EACH_PTR(tmp);
1036 
1037 	if (!possibly_true) {
1038 		add_ptr_list(false_stack, gate_sm);
1039 		return;
1040 	}
1041 
1042 	get_tf_stacks_from_pool(gate_sm->left, pool_sm, true_stack, false_stack);
1043 	get_tf_stacks_from_pool(gate_sm->right, pool_sm, true_stack, false_stack);
1044 }
1045 
1046 /*
1047  * The situation is we have a SMATCH_EXTRA state and we want to break it into
1048  * each of the ->possible states and find the implications of each.  The caller
1049  * has to use __push_fake_cur_stree() to preserve the correct states so they
1050  * can be restored later.
1051  */
1052 void overwrite_states_using_pool(struct sm_state *gate_sm, struct sm_state *pool_sm)
1053 {
1054 	struct state_list *true_stack = NULL;
1055 	struct state_list *false_stack = NULL;
1056 	struct stree *pre_stree;
1057 	struct stree *implied_true;
1058 	struct sm_state *tmp;
1059 
1060 	if (!pool_sm->pool)
1061 		return;
1062 
1063 	get_tf_stacks_from_pool(gate_sm, pool_sm, &true_stack, &false_stack);
1064 
1065 	pre_stree = clone_stree(__get_cur_stree());
1066 
1067 	implied_true = filter_stack(gate_sm, pre_stree, false_stack, true_stack);
1068 
1069 	free_stree(&pre_stree);
1070 	free_slist(&true_stack);
1071 	free_slist(&false_stack);
1072 
1073 	FOR_EACH_SM(implied_true, tmp) {
1074 		set_state(tmp->owner, tmp->name, tmp->sym, tmp->state);
1075 	} END_FOR_EACH_SM(tmp);
1076 
1077 	free_stree(&implied_true);
1078 }
1079 
1080 int assume(struct expression *expr)
1081 {
1082 	int orig_final_pass = final_pass;
1083 
1084 	in_fake_env++;
1085 	final_pass = 0;
1086 	__push_fake_cur_stree();
1087 	__split_whole_condition(expr);
1088 	final_pass = orig_final_pass;
1089 	in_fake_env--;
1090 
1091 	return 1;
1092 }
1093 
1094 void end_assume(void)
1095 {
1096 	__discard_false_states();
1097 	__free_fake_cur_stree();
1098 }
1099 
1100 int impossible_assumption(struct expression *left, int op, sval_t sval)
1101 {
1102 	struct expression *value;
1103 	struct expression *comparison;
1104 	int ret;
1105 
1106 	value = value_expr(sval.value);
1107 	comparison = compare_expression(left, op, value);
1108 
1109 	if (!assume(comparison))
1110 		return 0;
1111 	ret = is_impossible_path();
1112 	end_assume();
1113 
1114 	return ret;
1115 }
1116 
1117 void __extra_match_condition(struct expression *expr);
1118 void __comparison_match_condition(struct expression *expr);
1119 void __stored_condition(struct expression *expr);
1120 void register_implications(int id)
1121 {
1122 	add_hook(&save_implications_hook, CONDITION_HOOK);
1123 	add_hook(&set_implied_states, CONDITION_HOOK);
1124 	add_hook(&__extra_match_condition, CONDITION_HOOK);
1125 	add_hook(&set_extra_implied_states, CONDITION_HOOK);
1126 	add_hook(&__comparison_match_condition, CONDITION_HOOK);
1127 	add_hook(&__stored_condition, CONDITION_HOOK);
1128 	add_hook(&match_end_func, END_FUNC_HOOK);
1129 }
1130