Print this page
11506 smatch resync


  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 }


 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;


 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) {


 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);


 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




  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 int *dynamic_states;
 123 void allocate_dynamic_states_array(int num_checks)
 124 {
 125         dynamic_states = calloc(num_checks + 1, sizeof(int));
 126 }
 127 
 128 void set_dynamic_states(unsigned short owner)
 129 {
 130         dynamic_states[owner] = true;
 131 }
 132 
 133 bool has_dynamic_states(unsigned short owner)
 134 {
 135         if (owner >= num_checks)
 136                 return false;
 137         return dynamic_states[owner];
 138 }
 139 
 140 static int cmp_possible_sm(const struct sm_state *a, const struct sm_state *b, int preserve)
 141 {
 142         int ret;
 143 
 144         if (a == b)
 145                 return 0;

 146 
 147         if (!has_dynamic_states(a->owner)) {
 148                 if (a->state > b->state)
 149                         return -1;
 150                 if (a->state < b->state)
 151                         return 1;
 152                 return 0;
 153         }
 154 
 155         if (a->owner == SMATCH_EXTRA) {
 156                 /*
 157                  * In Smatch extra you can have borrowed implications.
 158                  *
 159                  * FIXME: review how borrowed implications work and if they
 160                  * are the best way.  See also smatch_implied.c.
 161                  *
 162                  */
 163                 ret = cmp_tracker(a, b);
 164                 if (ret)
 165                         return ret;
 166 
 167                 /*
 168                  * We want to preserve leaf states.  They're use to split
 169                  * returns in smatch_db.c.
 170                  *
 171                  */
 172                 if (preserve) {
 173                         if (a->merged && !b->merged)
 174                                 return -1;
 175                         if (!a->merged)
 176                                 return 1;
 177                 }
 178         }
 179         if (!a->state->name || !b->state->name)
 180                 return 0;
 181 
 182         return strcmp(a->state->name, b->state->name);
 183 }
 184 
 185 struct sm_state *alloc_sm_state(int owner, const char *name,
 186                                 struct symbol *sym, struct smatch_state *state)
 187 {
 188         struct sm_state *sm_state = __alloc_sm_state(0);
 189 
 190         sm_state_counter++;
 191 
 192         sm_state->name = alloc_sname(name);
 193         sm_state->owner = owner;
 194         sm_state->sym = sym;
 195         sm_state->state = state;
 196         sm_state->line = get_lineno();
 197         sm_state->merged = 0;
 198         sm_state->pool = NULL;
 199         sm_state->left = NULL;
 200         sm_state->right = NULL;

 201         sm_state->possible = NULL;
 202         add_ptr_list(&sm_state->possible, sm_state);
 203         return sm_state;
 204 }
 205 
 206 static struct sm_state *alloc_state_no_name(int owner, const char *name,
 207                                      struct symbol *sym,
 208                                      struct smatch_state *state)
 209 {
 210         struct sm_state *tmp;
 211 
 212         tmp = alloc_sm_state(owner, NULL, sym, state);
 213         tmp->name = name;
 214         return tmp;
 215 }
 216 
 217 int too_many_possible(struct sm_state *sm)
 218 {
 219         if (ptr_list_size((struct ptr_list *)sm->possible) >= 100)
 220                 return 1;
 221         return 0;
 222 }
 223 
 224 void add_possible_sm(struct sm_state *to, struct sm_state *new)
 225 {
 226         struct sm_state *tmp;
 227         int preserve = 1;
 228         int cmp;
 229 
 230         if (too_many_possible(to))
 231                 preserve = 0;
 232 
 233         FOR_EACH_PTR(to->possible, tmp) {
 234                 cmp = cmp_possible_sm(tmp, new, preserve);
 235                 if (cmp < 0)
 236                         continue;
 237                 else if (cmp == 0) {
 238                         return;
 239                 } else {
 240                         INSERT_CURRENT(new, tmp);
 241                         return;
 242                 }
 243         } END_FOR_EACH_PTR(tmp);
 244         add_ptr_list(&to->possible, new);
 245 }
 246 
 247 static void copy_possibles(struct sm_state *to, struct sm_state *one, struct sm_state *two)
 248 {
 249         struct sm_state *large = one;
 250         struct sm_state *small = two;
 251         struct sm_state *tmp;
 252 
 253         /*
 254          * We spend a lot of time copying the possible lists.  I've tried to
 255          * optimize the process a bit.
 256          *
 257          */
 258 
 259         if (ptr_list_size((struct ptr_list *)two->possible) >
 260             ptr_list_size((struct ptr_list *)one->possible)) {
 261                 large = two;
 262                 small = one;
 263         }
 264 
 265         to->possible = clone_slist(large->possible);
 266         add_possible_sm(to, to);
 267         FOR_EACH_PTR(small->possible, tmp) {
 268                 add_possible_sm(to, tmp);
 269         } END_FOR_EACH_PTR(tmp);
 270 }
 271 
 272 char *alloc_sname(const char *str)
 273 {
 274         char *tmp;
 275 
 276         if (!str)
 277                 return NULL;
 278         tmp = __alloc_sname(strlen(str) + 1);
 279         strcpy(tmp, str);
 280         return tmp;
 281 }
 282 
 283 static struct symbol *oom_func;
 284 static int oom_limit = 3000000;  /* Start with a 3GB limit */
 285 int out_of_memory(void)
 286 {
 287         if (oom_func)
 288                 return 1;
 289 
 290         /*
 291          * I decided to use 50M here based on trial and error.
 292          * It works out OK for the kernel and so it should work
 293          * for most other projects as well.
 294          */
 295         if (sm_state_counter * sizeof(struct sm_state) >= 100000000)
 296                 return 1;
 297 
 298         /*
 299          * We're reading from statm to figure out how much memory we
 300          * are using.  The problem is that at the end of the function
 301          * we release the memory, so that it can be re-used but it
 302          * stays in cache, it's not released to the OS.  So then if
 303          * we allocate memory for different purposes we can easily
 304          * hit the 3GB limit on the next function, so that's why I give
 305          * the next function an extra 100MB to work with.
 306          *
 307          */
 308         if (get_mem_kb() > oom_limit) {
 309                 oom_func = cur_func_sym;
 310                 final_pass++;
 311                 sm_perror("OOM: %luKb sm_state_count = %d", get_mem_kb(), sm_state_counter);
 312                 final_pass--;
 313                 return 1;
 314         }
 315 
 316         return 0;
 317 }
 318 
 319 int low_on_memory(void)
 320 {
 321         if (sm_state_counter * sizeof(struct sm_state) >= 25000000)
 322                 return 1;
 323         return 0;
 324 }
 325 
 326 static void free_sm_state(struct sm_state *sm)
 327 {
 328         free_slist(&sm->possible);
 329         /*
 330          * fixme.  Free the actual state.
 331          * Right now we leave it until the end of the function
 332          * because we don't want to double free it.
 333          * Use the freelist to not double free things
 334          */
 335 }


 350 {
 351         struct allocator_struct *desc = &sm_state_allocator;
 352         struct allocation_blob *blob = desc->blobs;
 353 
 354         desc->blobs = NULL;
 355         desc->allocations = 0;
 356         desc->total_bytes = 0;
 357         desc->useful_bytes = 0;
 358         desc->freelist = NULL;
 359         while (blob) {
 360                 struct allocation_blob *next = blob->next;
 361                 free_all_sm_states(blob);
 362                 blob_free(blob, desc->chunking);
 363                 blob = next;
 364         }
 365         clear_sname_alloc();
 366         clear_smatch_state_alloc();
 367 
 368         free_stack_and_strees(&all_pools);
 369         sm_state_counter = 0;
 370         if (oom_func) {
 371                 oom_limit += 100000;
 372                 oom_func = NULL;
 373         }
 374 }
 375 
 376 unsigned long get_pool_count(void)
 377 {
 378         return ptr_list_size((struct ptr_list *)all_pools);
 379 }
 380 
 381 struct sm_state *clone_sm(struct sm_state *s)
 382 {
 383         struct sm_state *ret;
 384 
 385         ret = alloc_state_no_name(s->owner, s->name, s->sym, s->state);
 386         ret->merged = s->merged;
 387         ret->line = s->line;
 388         /* clone_sm() doesn't copy the pools.  Each state needs to have
 389            only one pool. */
 390         ret->possible = clone_slist(s->possible);
 391         ret->left = s->left;
 392         ret->right = s->right;

 393         return ret;
 394 }
 395 
 396 int is_merged(struct sm_state *sm)
 397 {
 398         return sm->merged;
 399 }
 400 
 401 int is_leaf(struct sm_state *sm)
 402 {
 403         return !sm->merged;
 404 }
 405 
 406 int slist_has_state(struct state_list *slist, struct smatch_state *state)
 407 {
 408         struct sm_state *tmp;
 409 
 410         FOR_EACH_PTR(slist, tmp) {
 411                 if (tmp->state == state)
 412                         return 1;


 450 struct sm_state *merge_sm_states(struct sm_state *one, struct sm_state *two)
 451 {
 452         struct smatch_state *s;
 453         struct sm_state *result;
 454         static int warned;
 455 
 456         if (one == two)
 457                 return one;
 458         if (out_of_memory()) {
 459                 if (!warned)
 460                         sm_warning("Function too hairy.  No more merges.");
 461                 warned = 1;
 462                 return one;
 463         }
 464         warned = 0;
 465         s = merge_states(one->owner, one->name, one->sym, one->state, two->state);
 466         result = alloc_state_no_name(one->owner, one->name, one->sym, s);
 467         result->merged = 1;
 468         result->left = one;
 469         result->right = two;



 470 
 471         copy_possibles(result, one, two);
 472 
 473         /*
 474          * The ->line information is used by deref_check where we complain about
 475          * checking pointers that have already been dereferenced.  Let's say we
 476          * dereference a pointer on both the true and false paths and then merge
 477          * the states here.  The result state is &derefed, but the ->line number
 478          * is on the line where the pointer is merged not where it was
 479          * dereferenced..
 480          *
 481          * So in that case, let's just pick one dereference and set the ->line
 482          * to point at it.
 483          *
 484          */
 485 
 486         if (result->state == one->state)
 487                 result->line = one->line;
 488         if (result->state == two->state)
 489                 result->line = two->line;
 490 
 491         if (option_debug ||
 492             strcmp(check_name(one->owner), option_debug_check) == 0) {


 773         FOR_EACH_PTR(slist, sm) {
 774                 avl_insert(stree, sm);
 775         } END_FOR_EACH_PTR(sm);
 776 
 777         free_slist(&slist);
 778 }
 779 
 780 int __stree_id;
 781 
 782 /*
 783  * merge_slist() is called whenever paths merge, such as after
 784  * an if statement.  It takes the two slists and creates one.
 785  */
 786 static void __merge_stree(struct stree **to, struct stree *stree, int add_pool)
 787 {
 788         struct stree *results = NULL;
 789         struct stree *implied_one = NULL;
 790         struct stree *implied_two = NULL;
 791         AvlIter one_iter;
 792         AvlIter two_iter;
 793         struct sm_state *one, *two, *res;
 794 
 795         if (out_of_memory())
 796                 return;
 797 
 798         /* merging a null and nonnull path gives you only the nonnull path */
 799         if (!stree)
 800                 return;
 801         if (*to == stree)
 802                 return;
 803 
 804         if (!*to) {
 805                 *to = clone_stree(stree);
 806                 return;
 807         }
 808 
 809         implied_one = clone_stree(*to);
 810         implied_two = clone_stree(stree);
 811 
 812         match_states_stree(&implied_one, &implied_two);
 813         call_pre_merge_hooks(&implied_one, &implied_two);


 816                 clone_pool_havers_stree(&implied_one);
 817                 clone_pool_havers_stree(&implied_two);
 818 
 819                 set_stree_id(&implied_one, ++__stree_id);
 820                 set_stree_id(&implied_two, ++__stree_id);
 821                 if (implied_one->base_stree)
 822                         set_stree_id(&implied_one->base_stree, ++__stree_id);
 823                 if (implied_two->base_stree)
 824                         set_stree_id(&implied_two->base_stree, ++__stree_id);
 825         }
 826 
 827         push_stree(&all_pools, implied_one);
 828         push_stree(&all_pools, implied_two);
 829 
 830         avl_iter_begin(&one_iter, implied_one, FORWARD);
 831         avl_iter_begin(&two_iter, implied_two, FORWARD);
 832 
 833         for (;;) {
 834                 if (!one_iter.sm || !two_iter.sm)
 835                         break;
 836 
 837                 one = one_iter.sm;
 838                 two = two_iter.sm;
 839 
 840                 if (one == two) {
 841                         avl_insert(&results, one);
 842                         goto next;
 843                 }
 844 
 845                 if (add_pool) {
 846                         one->pool = implied_one;
 847                         if (implied_one->base_stree)
 848                                 one->pool = implied_one->base_stree;
 849                         two->pool = implied_two;
 850                         if (implied_two->base_stree)
 851                                 two->pool = implied_two->base_stree;
 852                 }
 853                 res = merge_sm_states(one, two);
 854                 add_possible_sm(res, one);
 855                 add_possible_sm(res, two);
 856                 avl_insert(&results, res);
 857 next:
 858                 avl_iter_next(&one_iter);
 859                 avl_iter_next(&two_iter);



 860         }

 861 
 862         free_stree(to);
 863         *to = results;
 864 }
 865 
 866 void merge_stree(struct stree **to, struct stree *stree)
 867 {
 868         __merge_stree(to, stree, 1);
 869 }
 870 
 871 void merge_stree_no_pools(struct stree **to, struct stree *stree)
 872 {
 873         __merge_stree(to, stree, 0);
 874 }
 875 
 876 /*
 877  * This is unfortunately a bit subtle...  The problem is that if a
 878  * state is set on one fake stree but not the other then we should
 879  * look up the the original state and use that as the unset state.
 880  * Fortunately, after you pop your fake stree then the cur_slist should