1 /*
2  * Copyright (C) 2008,2009 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 
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include "smatch.h"
21 #include "smatch_slist.h"
22 
23 #undef CHECKORDER
24 
25 ALLOCATOR(smatch_state, "smatch state");
26 ALLOCATOR(sm_state, "sm state");
27 ALLOCATOR(named_stree, "named slist");
28 __DO_ALLOCATOR(char, 1, 4, "state names", sname);
29 
30 int sm_state_counter;
31 
32 static struct stree_stack *all_pools;
33 
34 const char *show_sm(struct sm_state *sm)
35 {
36 	static char buf[256];
37 	struct sm_state *tmp;
38 	int pos;
39 	int i;
40 
41 	if (!sm)
42 		return "<none>";
43 
44 	pos = snprintf(buf, sizeof(buf), "[%s] '%s' = '%s'",
45 		       check_name(sm->owner), sm->name, show_state(sm->state));
46 	if (pos > sizeof(buf))
47 		goto truncate;
48 
49 	if (ptr_list_size((struct ptr_list *)sm->possible) == 1)
50 		return buf;
51 
52 	pos += snprintf(buf + pos, sizeof(buf) - pos, " (");
53 	if (pos > sizeof(buf))
54 		goto truncate;
55 	i = 0;
56 	FOR_EACH_PTR(sm->possible, tmp) {
57 		if (i++)
58 			pos += snprintf(buf + pos, sizeof(buf) - pos, ", ");
59 		if (pos > sizeof(buf))
60 			goto truncate;
61 		pos += snprintf(buf + pos, sizeof(buf) - pos, "%s",
62 			       show_state(tmp->state));
63 		if (pos > sizeof(buf))
64 			goto truncate;
65 	} END_FOR_EACH_PTR(tmp);
66 	snprintf(buf + pos, sizeof(buf) - pos, ")");
67 
68 	return buf;
69 
70 truncate:
71 	for (i = 0; i < 3; i++)
72 		buf[sizeof(buf) - 2 - i] = '.';
73 	return buf;
74 }
75 
76 void __print_stree(struct stree *stree)
77 {
78 	struct sm_state *sm;
79 
80 	printf("dumping stree at %d [%ld states]\n", get_lineno(), stree_count(stree));
81 	FOR_EACH_SM(stree, sm) {
82 		printf("%s\n", show_sm(sm));
83 	} END_FOR_EACH_SM(sm);
84 	printf("---\n");
85 }
86 
87 /* NULL states go at the end to simplify merge_slist */
88 int cmp_tracker(const struct sm_state *a, const struct sm_state *b)
89 {
90 	int ret;
91 
92 	if (a == b)
93 		return 0;
94 	if (!b)
95 		return -1;
96 	if (!a)
97 		return 1;
98 
99 	if (a->owner > b->owner)
100 		return -1;
101 	if (a->owner < b->owner)
102 		return 1;
103 
104 	ret = strcmp(a->name, b->name);
105 	if (ret < 0)
106 		return -1;
107 	if (ret > 0)
108 		return 1;
109 
110 	if (!b->sym && a->sym)
111 		return -1;
112 	if (!a->sym && b->sym)
113 		return 1;
114 	if (a->sym < b->sym)
115 		return -1;
116 	if (a->sym > b->sym)
117 		return 1;
118 
119 	return 0;
120 }
121 
122 static int cmp_sm_states(const struct sm_state *a, const struct sm_state *b, int preserve)
123 {
124 	int ret;
125 
126 	ret = cmp_tracker(a, b);
127 	if (ret)
128 		return ret;
129 
130 	/* todo:  add hook for smatch_extra.c */
131 	if (a->state > b->state)
132 		return -1;
133 	if (a->state < b->state)
134 		return 1;
135 	/* This is obviously a massive disgusting hack but we need to preserve
136 	 * the unmerged states for smatch extra because we use them in
137 	 * smatch_db.c.  Meanwhile if we preserve all the other unmerged states
138 	 * then it uses a lot of memory and we don't use it.  Hence this hack.
139 	 *
140 	 * Also sometimes even just preserving every possible SMATCH_EXTRA state
141 	 * takes too much resources so we have to cap that.  Capping is probably
142 	 * not often a problem in real life.
143 	 */
144 	if (a->owner == SMATCH_EXTRA && preserve) {
145 		if (a == b)
146 			return 0;
147 		if (a->merged == 1 && b->merged == 0)
148 			return -1;
149 		if (a->merged == 0)
150 			return 1;
151 	}
152 
153 	return 0;
154 }
155 
156 struct sm_state *alloc_sm_state(int owner, const char *name,
157 				struct symbol *sym, struct smatch_state *state)
158 {
159 	struct sm_state *sm_state = __alloc_sm_state(0);
160 
161 	sm_state_counter++;
162 
163 	sm_state->name = alloc_sname(name);
164 	sm_state->owner = owner;
165 	sm_state->sym = sym;
166 	sm_state->state = state;
167 	sm_state->line = get_lineno();
168 	sm_state->merged = 0;
169 	sm_state->pool = NULL;
170 	sm_state->left = NULL;
171 	sm_state->right = NULL;
172 	sm_state->nr_children = 1;
173 	sm_state->possible = NULL;
174 	add_ptr_list(&sm_state->possible, sm_state);
175 	return sm_state;
176 }
177 
178 static struct sm_state *alloc_state_no_name(int owner, const char *name,
179 				     struct symbol *sym,
180 				     struct smatch_state *state)
181 {
182 	struct sm_state *tmp;
183 
184 	tmp = alloc_sm_state(owner, NULL, sym, state);
185 	tmp->name = name;
186 	return tmp;
187 }
188 
189 int too_many_possible(struct sm_state *sm)
190 {
191 	if (ptr_list_size((struct ptr_list *)sm->possible) >= 100)
192 		return 1;
193 	return 0;
194 }
195 
196 void add_possible_sm(struct sm_state *to, struct sm_state *new)
197 {
198 	struct sm_state *tmp;
199 	int preserve = 1;
200 
201 	if (too_many_possible(to))
202 		preserve = 0;
203 
204 	FOR_EACH_PTR(to->possible, tmp) {
205 		if (cmp_sm_states(tmp, new, preserve) < 0)
206 			continue;
207 		else if (cmp_sm_states(tmp, new, preserve) == 0) {
208 			return;
209 		} else {
210 			INSERT_CURRENT(new, tmp);
211 			return;
212 		}
213 	} END_FOR_EACH_PTR(tmp);
214 	add_ptr_list(&to->possible, new);
215 }
216 
217 static void copy_possibles(struct sm_state *to, struct sm_state *from)
218 {
219 	struct sm_state *tmp;
220 
221 	FOR_EACH_PTR(from->possible, tmp) {
222 		add_possible_sm(to, tmp);
223 	} END_FOR_EACH_PTR(tmp);
224 }
225 
226 char *alloc_sname(const char *str)
227 {
228 	char *tmp;
229 
230 	if (!str)
231 		return NULL;
232 	tmp = __alloc_sname(strlen(str) + 1);
233 	strcpy(tmp, str);
234 	return tmp;
235 }
236 
237 int out_of_memory(void)
238 {
239 	/*
240 	 * I decided to use 50M here based on trial and error.
241 	 * It works out OK for the kernel and so it should work
242 	 * for most other projects as well.
243 	 */
244 	if (sm_state_counter * sizeof(struct sm_state) >= 100000000)
245 		return 1;
246 	return 0;
247 }
248 
249 int low_on_memory(void)
250 {
251 	if (sm_state_counter * sizeof(struct sm_state) >= 25000000)
252 		return 1;
253 	return 0;
254 }
255 
256 static void free_sm_state(struct sm_state *sm)
257 {
258 	free_slist(&sm->possible);
259 	/*
260 	 * fixme.  Free the actual state.
261 	 * Right now we leave it until the end of the function
262 	 * because we don't want to double free it.
263 	 * Use the freelist to not double free things
264 	 */
265 }
266 
267 static void free_all_sm_states(struct allocation_blob *blob)
268 {
269 	unsigned int size = sizeof(struct sm_state);
270 	unsigned int offset = 0;
271 
272 	while (offset < blob->offset) {
273 		free_sm_state((struct sm_state *)(blob->data + offset));
274 		offset += size;
275 	}
276 }
277 
278 /* At the end of every function we free all the sm_states */
279 void free_every_single_sm_state(void)
280 {
281 	struct allocator_struct *desc = &sm_state_allocator;
282 	struct allocation_blob *blob = desc->blobs;
283 
284 	desc->blobs = NULL;
285 	desc->allocations = 0;
286 	desc->total_bytes = 0;
287 	desc->useful_bytes = 0;
288 	desc->freelist = NULL;
289 	while (blob) {
290 		struct allocation_blob *next = blob->next;
291 		free_all_sm_states(blob);
292 		blob_free(blob, desc->chunking);
293 		blob = next;
294 	}
295 	clear_sname_alloc();
296 	clear_smatch_state_alloc();
297 
298 	free_stack_and_strees(&all_pools);
299 	sm_state_counter = 0;
300 }
301 
302 unsigned long get_pool_count(void)
303 {
304 	return ptr_list_size((struct ptr_list *)all_pools);
305 }
306 
307 struct sm_state *clone_sm(struct sm_state *s)
308 {
309 	struct sm_state *ret;
310 
311 	ret = alloc_state_no_name(s->owner, s->name, s->sym, s->state);
312 	ret->merged = s->merged;
313 	ret->line = s->line;
314 	/* clone_sm() doesn't copy the pools.  Each state needs to have
315 	   only one pool. */
316 	ret->possible = clone_slist(s->possible);
317 	ret->left = s->left;
318 	ret->right = s->right;
319 	ret->nr_children = s->nr_children;
320 	return ret;
321 }
322 
323 int is_merged(struct sm_state *sm)
324 {
325 	return sm->merged;
326 }
327 
328 int is_leaf(struct sm_state *sm)
329 {
330 	return !sm->merged;
331 }
332 
333 int slist_has_state(struct state_list *slist, struct smatch_state *state)
334 {
335 	struct sm_state *tmp;
336 
337 	FOR_EACH_PTR(slist, tmp) {
338 		if (tmp->state == state)
339 			return 1;
340 	} END_FOR_EACH_PTR(tmp);
341 	return 0;
342 }
343 
344 struct state_list *clone_slist(struct state_list *from_slist)
345 {
346 	struct sm_state *sm;
347 	struct state_list *to_slist = NULL;
348 
349 	FOR_EACH_PTR(from_slist, sm) {
350 		add_ptr_list(&to_slist, sm);
351 	} END_FOR_EACH_PTR(sm);
352 	return to_slist;
353 }
354 
355 static struct smatch_state *merge_states(int owner, const char *name,
356 					 struct symbol *sym,
357 					 struct smatch_state *state1,
358 					 struct smatch_state *state2)
359 {
360 	struct smatch_state *ret;
361 
362 	if (state1 == state2)
363 		ret = state1;
364 	else if (__has_merge_function(owner))
365 		ret = __client_merge_function(owner, state1, state2);
366 	else if (state1 == &ghost)
367 		ret = state2;
368 	else if (state2 == &ghost)
369 		ret = state1;
370 	else if (!state1 || !state2)
371 		ret = &undefined;
372 	else
373 		ret = &merged;
374 	return ret;
375 }
376 
377 struct sm_state *merge_sm_states(struct sm_state *one, struct sm_state *two)
378 {
379 	struct smatch_state *s;
380 	struct sm_state *result;
381 	static int warned;
382 
383 	if (one == two)
384 		return one;
385 	if (out_of_memory()) {
386 		if (!warned)
387 			sm_warning("Function too hairy.  No more merges.");
388 		warned = 1;
389 		return one;
390 	}
391 	warned = 0;
392 	s = merge_states(one->owner, one->name, one->sym, one->state, two->state);
393 	result = alloc_state_no_name(one->owner, one->name, one->sym, s);
394 	result->merged = 1;
395 	result->left = one;
396 	result->right = two;
397 	result->nr_children = one->nr_children + two->nr_children;
398 	copy_possibles(result, one);
399 	copy_possibles(result, two);
400 
401 	/*
402 	 * The ->line information is used by deref_check where we complain about
403 	 * checking pointers that have already been dereferenced.  Let's say we
404 	 * dereference a pointer on both the true and false paths and then merge
405 	 * the states here.  The result state is &derefed, but the ->line number
406 	 * is on the line where the pointer is merged not where it was
407 	 * dereferenced..
408 	 *
409 	 * So in that case, let's just pick one dereference and set the ->line
410 	 * to point at it.
411 	 *
412 	 */
413 
414 	if (result->state == one->state)
415 		result->line = one->line;
416 	if (result->state == two->state)
417 		result->line = two->line;
418 
419 	if (option_debug ||
420 	    strcmp(check_name(one->owner), option_debug_check) == 0) {
421 		struct sm_state *tmp;
422 		int i = 0;
423 
424 		printf("%s:%d %s() merge [%s] '%s' %s(L %d) + %s(L %d) => %s (",
425 			get_filename(), get_lineno(), get_function(),
426 			check_name(one->owner), one->name,
427 			show_state(one->state), one->line,
428 			show_state(two->state), two->line,
429 			show_state(s));
430 
431 		FOR_EACH_PTR(result->possible, tmp) {
432 			if (i++)
433 				printf(", ");
434 			printf("%s", show_state(tmp->state));
435 		} END_FOR_EACH_PTR(tmp);
436 		printf(")\n");
437 	}
438 
439 	return result;
440 }
441 
442 struct sm_state *get_sm_state_stree(struct stree *stree, int owner, const char *name,
443 				struct symbol *sym)
444 {
445 	struct tracker tracker = {
446 		.owner = owner,
447 		.name = (char *)name,
448 		.sym = sym,
449 	};
450 
451 	if (!name)
452 		return NULL;
453 
454 
455 	return avl_lookup(stree, (struct sm_state *)&tracker);
456 }
457 
458 struct smatch_state *get_state_stree(struct stree *stree,
459 				int owner, const char *name,
460 				struct symbol *sym)
461 {
462 	struct sm_state *sm;
463 
464 	sm = get_sm_state_stree(stree, owner, name, sym);
465 	if (sm)
466 		return sm->state;
467 	return NULL;
468 }
469 
470 /* FIXME: this is almost exactly the same as set_sm_state_slist() */
471 void overwrite_sm_state_stree(struct stree **stree, struct sm_state *new)
472 {
473 	avl_insert(stree, new);
474 }
475 
476 void overwrite_sm_state_stree_stack(struct stree_stack **stack,
477 			struct sm_state *sm)
478 {
479 	struct stree *stree;
480 
481 	stree = pop_stree(stack);
482 	overwrite_sm_state_stree(&stree, sm);
483 	push_stree(stack, stree);
484 }
485 
486 struct sm_state *set_state_stree(struct stree **stree, int owner, const char *name,
487 		     struct symbol *sym, struct smatch_state *state)
488 {
489 	struct sm_state *new = alloc_sm_state(owner, name, sym, state);
490 
491 	avl_insert(stree, new);
492 	return new;
493 }
494 
495 void set_state_stree_perm(struct stree **stree, int owner, const char *name,
496 		     struct symbol *sym, struct smatch_state *state)
497 {
498 	struct sm_state *sm;
499 
500 	sm = malloc(sizeof(*sm) + strlen(name) + 1);
501 	memset(sm, 0, sizeof(*sm));
502 	sm->owner = owner;
503 	sm->name = (char *)(sm + 1);
504 	strcpy((char *)sm->name, name);
505 	sm->sym = sym;
506 	sm->state = state;
507 
508 	overwrite_sm_state_stree(stree, sm);
509 }
510 
511 void delete_state_stree(struct stree **stree, int owner, const char *name,
512 			struct symbol *sym)
513 {
514 	struct tracker tracker = {
515 		.owner = owner,
516 		.name = (char *)name,
517 		.sym = sym,
518 	};
519 
520 	avl_remove(stree, (struct sm_state *)&tracker);
521 }
522 
523 void delete_state_stree_stack(struct stree_stack **stack, int owner, const char *name,
524 			struct symbol *sym)
525 {
526 	struct stree *stree;
527 
528 	stree = pop_stree(stack);
529 	delete_state_stree(&stree, owner, name, sym);
530 	push_stree(stack, stree);
531 }
532 
533 void push_stree(struct stree_stack **stack, struct stree *stree)
534 {
535 	add_ptr_list(stack, stree);
536 }
537 
538 struct stree *pop_stree(struct stree_stack **stack)
539 {
540 	struct stree *stree;
541 
542 	stree = last_ptr_list((struct ptr_list *)*stack);
543 	delete_ptr_list_last((struct ptr_list **)stack);
544 	return stree;
545 }
546 
547 struct stree *top_stree(struct stree_stack *stack)
548 {
549 	return last_ptr_list((struct ptr_list *)stack);
550 }
551 
552 void free_slist(struct state_list **slist)
553 {
554 	__free_ptr_list((struct ptr_list **)slist);
555 }
556 
557 void free_stree_stack(struct stree_stack **stack)
558 {
559 	__free_ptr_list((struct ptr_list **)stack);
560 }
561 
562 void free_stack_and_strees(struct stree_stack **stree_stack)
563 {
564 	struct stree *stree;
565 
566 	FOR_EACH_PTR(*stree_stack, stree) {
567 		free_stree(&stree);
568 	} END_FOR_EACH_PTR(stree);
569 	free_stree_stack(stree_stack);
570 }
571 
572 struct sm_state *set_state_stree_stack(struct stree_stack **stack, int owner, const char *name,
573 				struct symbol *sym, struct smatch_state *state)
574 {
575 	struct stree *stree;
576 	struct sm_state *sm;
577 
578 	stree = pop_stree(stack);
579 	sm = set_state_stree(&stree, owner, name, sym, state);
580 	push_stree(stack, stree);
581 
582 	return sm;
583 }
584 
585 /*
586  * get_sm_state_stack() gets the state for the top slist on the stack.
587  */
588 struct sm_state *get_sm_state_stree_stack(struct stree_stack *stack,
589 				int owner, const char *name,
590 				struct symbol *sym)
591 {
592 	struct stree *stree;
593 	struct sm_state *ret;
594 
595 	stree = pop_stree(&stack);
596 	ret = get_sm_state_stree(stree, owner, name, sym);
597 	push_stree(&stack, stree);
598 	return ret;
599 }
600 
601 struct smatch_state *get_state_stree_stack(struct stree_stack *stack,
602 				int owner, const char *name,
603 				struct symbol *sym)
604 {
605 	struct sm_state *sm;
606 
607 	sm = get_sm_state_stree_stack(stack, owner, name, sym);
608 	if (sm)
609 		return sm->state;
610 	return NULL;
611 }
612 
613 static void match_states_stree(struct stree **one, struct stree **two)
614 {
615 	struct smatch_state *tmp_state;
616 	struct sm_state *sm;
617 	struct state_list *add_to_one = NULL;
618 	struct state_list *add_to_two = NULL;
619 	AvlIter one_iter;
620 	AvlIter two_iter;
621 
622 	avl_iter_begin(&one_iter, *one, FORWARD);
623 	avl_iter_begin(&two_iter, *two, FORWARD);
624 
625 	for (;;) {
626 		if (!one_iter.sm && !two_iter.sm)
627 			break;
628 		if (cmp_tracker(one_iter.sm, two_iter.sm) < 0) {
629 			__set_fake_cur_stree_fast(*two);
630 			tmp_state = __client_unmatched_state_function(one_iter.sm);
631 			__pop_fake_cur_stree_fast();
632 			sm = alloc_state_no_name(one_iter.sm->owner, one_iter.sm->name,
633 						  one_iter.sm->sym, tmp_state);
634 			add_ptr_list(&add_to_two, sm);
635 			avl_iter_next(&one_iter);
636 		} else if (cmp_tracker(one_iter.sm, two_iter.sm) == 0) {
637 			avl_iter_next(&one_iter);
638 			avl_iter_next(&two_iter);
639 		} else {
640 			__set_fake_cur_stree_fast(*one);
641 			tmp_state = __client_unmatched_state_function(two_iter.sm);
642 			__pop_fake_cur_stree_fast();
643 			sm = alloc_state_no_name(two_iter.sm->owner, two_iter.sm->name,
644 						  two_iter.sm->sym, tmp_state);
645 			add_ptr_list(&add_to_one, sm);
646 			avl_iter_next(&two_iter);
647 		}
648 	}
649 
650 	FOR_EACH_PTR(add_to_one, sm) {
651 		avl_insert(one, sm);
652 	} END_FOR_EACH_PTR(sm);
653 
654 	FOR_EACH_PTR(add_to_two, sm) {
655 		avl_insert(two, sm);
656 	} END_FOR_EACH_PTR(sm);
657 
658 	free_slist(&add_to_one);
659 	free_slist(&add_to_two);
660 }
661 
662 static void call_pre_merge_hooks(struct stree **one, struct stree **two)
663 {
664 	struct sm_state *sm, *other;
665 
666 	save_all_states();
667 
668 	__swap_cur_stree(*one);
669 	FOR_EACH_SM(*two, sm) {
670 		other = get_sm_state(sm->owner, sm->name, sm->sym);
671 		if (other == sm)
672 			continue;
673 		call_pre_merge_hook(sm);
674 	} END_FOR_EACH_SM(sm);
675 	*one = clone_stree(__get_cur_stree());
676 
677 	__swap_cur_stree(*two);
678 	FOR_EACH_SM(*one, sm) {
679 		other = get_sm_state(sm->owner, sm->name, sm->sym);
680 		if (other == sm)
681 			continue;
682 		call_pre_merge_hook(sm);
683 	} END_FOR_EACH_SM(sm);
684 	*two = clone_stree(__get_cur_stree());
685 
686 	restore_all_states();
687 }
688 
689 static void clone_pool_havers_stree(struct stree **stree)
690 {
691 	struct sm_state *sm, *tmp;
692 	struct state_list *slist = NULL;
693 
694 	FOR_EACH_SM(*stree, sm) {
695 		if (sm->pool) {
696 			tmp = clone_sm(sm);
697 			add_ptr_list(&slist, tmp);
698 		}
699 	} END_FOR_EACH_SM(sm);
700 
701 	FOR_EACH_PTR(slist, sm) {
702 		avl_insert(stree, sm);
703 	} END_FOR_EACH_PTR(sm);
704 
705 	free_slist(&slist);
706 }
707 
708 int __stree_id;
709 
710 /*
711  * merge_slist() is called whenever paths merge, such as after
712  * an if statement.  It takes the two slists and creates one.
713  */
714 static void __merge_stree(struct stree **to, struct stree *stree, int add_pool)
715 {
716 	struct stree *results = NULL;
717 	struct stree *implied_one = NULL;
718 	struct stree *implied_two = NULL;
719 	AvlIter one_iter;
720 	AvlIter two_iter;
721 	struct sm_state *tmp_sm;
722 
723 	if (out_of_memory())
724 		return;
725 
726 	/* merging a null and nonnull path gives you only the nonnull path */
727 	if (!stree)
728 		return;
729 	if (*to == stree)
730 		return;
731 
732 	if (!*to) {
733 		*to = clone_stree(stree);
734 		return;
735 	}
736 
737 	implied_one = clone_stree(*to);
738 	implied_two = clone_stree(stree);
739 
740 	match_states_stree(&implied_one, &implied_two);
741 	call_pre_merge_hooks(&implied_one, &implied_two);
742 
743 	if (add_pool) {
744 		clone_pool_havers_stree(&implied_one);
745 		clone_pool_havers_stree(&implied_two);
746 
747 		set_stree_id(&implied_one, ++__stree_id);
748 		set_stree_id(&implied_two, ++__stree_id);
749 		if (implied_one->base_stree)
750 			set_stree_id(&implied_one->base_stree, ++__stree_id);
751 		if (implied_two->base_stree)
752 			set_stree_id(&implied_two->base_stree, ++__stree_id);
753 	}
754 
755 	push_stree(&all_pools, implied_one);
756 	push_stree(&all_pools, implied_two);
757 
758 	avl_iter_begin(&one_iter, implied_one, FORWARD);
759 	avl_iter_begin(&two_iter, implied_two, FORWARD);
760 
761 	for (;;) {
762 		if (!one_iter.sm || !two_iter.sm)
763 			break;
764 		if (cmp_tracker(one_iter.sm, two_iter.sm) < 0) {
765 			sm_perror(" in %s", __func__);
766 			avl_iter_next(&one_iter);
767 		} else if (cmp_tracker(one_iter.sm, two_iter.sm) == 0) {
768 			if (add_pool && one_iter.sm != two_iter.sm) {
769 				one_iter.sm->pool = implied_one;
770 				if (implied_one->base_stree)
771 					one_iter.sm->pool = implied_one->base_stree;
772 				two_iter.sm->pool = implied_two;
773 				if (implied_two->base_stree)
774 					two_iter.sm->pool = implied_two->base_stree;
775 			}
776 			tmp_sm = merge_sm_states(one_iter.sm, two_iter.sm);
777 			add_possible_sm(tmp_sm, one_iter.sm);
778 			add_possible_sm(tmp_sm, two_iter.sm);
779 			avl_insert(&results, tmp_sm);
780 			avl_iter_next(&one_iter);
781 			avl_iter_next(&two_iter);
782 		} else {
783 			sm_perror(" in %s", __func__);
784 			avl_iter_next(&two_iter);
785 		}
786 	}
787 
788 	free_stree(to);
789 	*to = results;
790 }
791 
792 void merge_stree(struct stree **to, struct stree *stree)
793 {
794 	__merge_stree(to, stree, 1);
795 }
796 
797 void merge_stree_no_pools(struct stree **to, struct stree *stree)
798 {
799 	__merge_stree(to, stree, 0);
800 }
801 
802 /*
803  * This is unfortunately a bit subtle...  The problem is that if a
804  * state is set on one fake stree but not the other then we should
805  * look up the the original state and use that as the unset state.
806  * Fortunately, after you pop your fake stree then the cur_slist should
807  * reflect the original state.
808  */
809 void merge_fake_stree(struct stree **to, struct stree *stree)
810 {
811 	struct stree *one = *to;
812 	struct stree *two = stree;
813 	struct sm_state *sm;
814 	struct state_list *add_to_one = NULL;
815 	struct state_list *add_to_two = NULL;
816 	AvlIter one_iter;
817 	AvlIter two_iter;
818 
819 	if (!stree)
820 		return;
821 	if (*to == stree)
822 		return;
823 	if (!*to) {
824 		*to = clone_stree(stree);
825 		return;
826 	}
827 
828 	avl_iter_begin(&one_iter, one, FORWARD);
829 	avl_iter_begin(&two_iter, two, FORWARD);
830 
831 	for (;;) {
832 		if (!one_iter.sm && !two_iter.sm)
833 			break;
834 		if (cmp_tracker(one_iter.sm, two_iter.sm) < 0) {
835 			sm = get_sm_state(one_iter.sm->owner, one_iter.sm->name,
836 					  one_iter.sm->sym);
837 			if (sm)
838 				add_ptr_list(&add_to_two, sm);
839 			avl_iter_next(&one_iter);
840 		} else if (cmp_tracker(one_iter.sm, two_iter.sm) == 0) {
841 			avl_iter_next(&one_iter);
842 			avl_iter_next(&two_iter);
843 		} else {
844 			sm = get_sm_state(two_iter.sm->owner, two_iter.sm->name,
845 					  two_iter.sm->sym);
846 			if (sm)
847 				add_ptr_list(&add_to_one, sm);
848 			avl_iter_next(&two_iter);
849 		}
850 	}
851 
852 	FOR_EACH_PTR(add_to_one, sm) {
853 		avl_insert(&one, sm);
854 	} END_FOR_EACH_PTR(sm);
855 
856 	FOR_EACH_PTR(add_to_two, sm) {
857 		avl_insert(&two, sm);
858 	} END_FOR_EACH_PTR(sm);
859 
860 	one->base_stree = clone_stree(__get_cur_stree());
861 	FOR_EACH_SM(one, sm) {
862 		avl_insert(&one->base_stree, sm);
863 	} END_FOR_EACH_SM(sm);
864 
865 	two->base_stree = clone_stree(__get_cur_stree());
866 	FOR_EACH_SM(two, sm) {
867 		avl_insert(&two->base_stree, sm);
868 	} END_FOR_EACH_SM(sm);
869 
870 	free_slist(&add_to_one);
871 	free_slist(&add_to_two);
872 
873 	__merge_stree(&one, two, 1);
874 
875 	*to = one;
876 }
877 
878 /*
879  * filter_slist() removes any sm states "slist" holds in common with "filter"
880  */
881 void filter_stree(struct stree **stree, struct stree *filter)
882 {
883 	struct stree *results = NULL;
884 	AvlIter one_iter;
885 	AvlIter two_iter;
886 
887 	avl_iter_begin(&one_iter, *stree, FORWARD);
888 	avl_iter_begin(&two_iter, filter, FORWARD);
889 
890 	/* FIXME: This should probably be re-written with trees in mind */
891 
892 	for (;;) {
893 		if (!one_iter.sm && !two_iter.sm)
894 			break;
895 		if (cmp_tracker(one_iter.sm, two_iter.sm) < 0) {
896 			avl_insert(&results, one_iter.sm);
897 			avl_iter_next(&one_iter);
898 		} else if (cmp_tracker(one_iter.sm, two_iter.sm) == 0) {
899 			if (one_iter.sm != two_iter.sm)
900 				avl_insert(&results, one_iter.sm);
901 			avl_iter_next(&one_iter);
902 			avl_iter_next(&two_iter);
903 		} else {
904 			avl_iter_next(&two_iter);
905 		}
906 	}
907 
908 	free_stree(stree);
909 	*stree = results;
910 }
911 
912 
913 /*
914  * and_slist_stack() pops the top two slists, overwriting the one with
915  * the other and pushing it back on the stack.
916  */
917 void and_stree_stack(struct stree_stack **stack)
918 {
919 	struct sm_state *tmp;
920 	struct stree *right_stree = pop_stree(stack);
921 
922 	FOR_EACH_SM(right_stree, tmp) {
923 		overwrite_sm_state_stree_stack(stack, tmp);
924 	} END_FOR_EACH_SM(tmp);
925 	free_stree(&right_stree);
926 }
927 
928 /*
929  * or_slist_stack() is for if we have:  if (foo || bar) { foo->baz;
930  * It pops the two slists from the top of the stack and merges them
931  * together in a way that preserves the things they have in common
932  * but creates a merged state for most of the rest.
933  * You could have code that had:  if (foo || foo) { foo->baz;
934  * It's this function which ensures smatch does the right thing.
935  */
936 void or_stree_stack(struct stree_stack **pre_conds,
937 		    struct stree *cur_stree,
938 		    struct stree_stack **stack)
939 {
940 	struct stree *new;
941 	struct stree *old;
942 	struct stree *pre_stree;
943 	struct stree *res;
944 	struct stree *tmp_stree;
945 
946 	new = pop_stree(stack);
947 	old = pop_stree(stack);
948 
949 	pre_stree = pop_stree(pre_conds);
950 	push_stree(pre_conds, clone_stree(pre_stree));
951 
952 	res = clone_stree(pre_stree);
953 	overwrite_stree(old, &res);
954 
955 	tmp_stree = clone_stree(cur_stree);
956 	overwrite_stree(new, &tmp_stree);
957 
958 	merge_stree(&res, tmp_stree);
959 	filter_stree(&res, pre_stree);
960 
961 	push_stree(stack, res);
962 	free_stree(&tmp_stree);
963 	free_stree(&pre_stree);
964 	free_stree(&new);
965 	free_stree(&old);
966 }
967 
968 /*
969  * get_named_stree() is only used for gotos.
970  */
971 struct stree **get_named_stree(struct named_stree_stack *stack,
972 			       const char *name,
973 			       struct symbol *sym)
974 {
975 	struct named_stree *tmp;
976 
977 	FOR_EACH_PTR(stack, tmp) {
978 		if (tmp->sym == sym &&
979 		    strcmp(tmp->name, name) == 0)
980 			return &tmp->stree;
981 	} END_FOR_EACH_PTR(tmp);
982 	return NULL;
983 }
984 
985 /* FIXME:  These parameters are in a different order from expected */
986 void overwrite_stree(struct stree *from, struct stree **to)
987 {
988 	struct sm_state *tmp;
989 
990 	FOR_EACH_SM(from, tmp) {
991 		overwrite_sm_state_stree(to, tmp);
992 	} END_FOR_EACH_SM(tmp);
993 }
994 
995