1 /*
   2  * Copyright (C) 2012 Oracle.
   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 /*
  19  * The point here is to store the relationships between two variables.
  20  * Ie:  y > x.
  21  * To do that we create a state with the two variables in alphabetical order:
  22  * ->name = "x vs y" and the state would be "<".  On the false path the state
  23  * would be ">=".
  24  *
  25  * Part of the trick of it is that if x or y is modified then we need to reset
  26  * the state.  We need to keep a list of all the states which depend on x and
  27  * all the states which depend on y.  The link_id code handles this.
  28  *
  29  */
  30 
  31 #include "smatch.h"
  32 #include "smatch_extra.h"
  33 #include "smatch_slist.h"
  34 
  35 static int compare_id;
  36 static int link_id;
  37 static int inc_dec_id;
  38 static int inc_dec_link_id;
  39 
  40 static void add_comparison(struct expression *left, int comparison, struct expression *right);
  41 
  42 /* for handling for loops */
  43 STATE(start);
  44 STATE(incremented);
  45 
  46 ALLOCATOR(compare_data, "compare data");
  47 
  48 static struct symbol *vsl_to_sym(struct var_sym_list *vsl)
  49 {
  50         struct var_sym *vs;
  51 
  52         if (!vsl)
  53                 return NULL;
  54         if (ptr_list_size((struct ptr_list *)vsl) != 1)
  55                 return NULL;
  56         vs = first_ptr_list((struct ptr_list *)vsl);
  57         return vs->sym;
  58 }
  59 
  60 struct smatch_state *alloc_compare_state(
  61                 struct expression *left,
  62                 const char *left_var, struct var_sym_list *left_vsl,
  63                 int comparison,
  64                 struct expression *right,
  65                 const char *right_var, struct var_sym_list *right_vsl)
  66 {
  67         struct smatch_state *state;
  68         struct compare_data *data;
  69 
  70         state = __alloc_smatch_state(0);
  71         state->name = alloc_sname(show_special(comparison));
  72         data = __alloc_compare_data(0);
  73         data->left = left;
  74         data->left_var = alloc_sname(left_var);
  75         data->left_vsl = clone_var_sym_list(left_vsl);
  76         data->comparison = comparison;
  77         data->right = right;
  78         data->right_var = alloc_sname(right_var);
  79         data->right_vsl = clone_var_sym_list(right_vsl);
  80         state->data = data;
  81         return state;
  82 }
  83 
  84 int state_to_comparison(struct smatch_state *state)
  85 {
  86         if (!state || !state->data)
  87                 return 0;
  88         return ((struct compare_data *)state->data)->comparison;
  89 }
  90 
  91 /*
  92  * flip_comparison() reverses the op left and right.  So "x >= y" becomes "y <= x".
  93  */
  94 int flip_comparison(int op)
  95 {
  96         switch (op) {
  97         case 0:
  98                 return 0;
  99         case '<':
 100                 return '>';
 101         case SPECIAL_UNSIGNED_LT:
 102                 return SPECIAL_UNSIGNED_GT;
 103         case SPECIAL_LTE:
 104                 return SPECIAL_GTE;
 105         case SPECIAL_UNSIGNED_LTE:
 106                 return SPECIAL_UNSIGNED_GTE;
 107         case SPECIAL_EQUAL:
 108                 return SPECIAL_EQUAL;
 109         case SPECIAL_NOTEQUAL:
 110                 return SPECIAL_NOTEQUAL;
 111         case SPECIAL_GTE:
 112                 return SPECIAL_LTE;
 113         case SPECIAL_UNSIGNED_GTE:
 114                 return SPECIAL_UNSIGNED_LTE;
 115         case '>':
 116                 return '<';
 117         case SPECIAL_UNSIGNED_GT:
 118                 return SPECIAL_UNSIGNED_LT;
 119         default:
 120                 sm_perror("unhandled comparison %d", op);
 121                 return op;
 122         }
 123 }
 124 
 125 int negate_comparison(int op)
 126 {
 127         switch (op) {
 128         case 0:
 129                 return 0;
 130         case '<':
 131                 return SPECIAL_GTE;
 132         case SPECIAL_UNSIGNED_LT:
 133                 return SPECIAL_UNSIGNED_GTE;
 134         case SPECIAL_LTE:
 135                 return '>';
 136         case SPECIAL_UNSIGNED_LTE:
 137                 return SPECIAL_UNSIGNED_GT;
 138         case SPECIAL_EQUAL:
 139                 return SPECIAL_NOTEQUAL;
 140         case SPECIAL_NOTEQUAL:
 141                 return SPECIAL_EQUAL;
 142         case SPECIAL_GTE:
 143                 return '<';
 144         case SPECIAL_UNSIGNED_GTE:
 145                 return SPECIAL_UNSIGNED_LT;
 146         case '>':
 147                 return SPECIAL_LTE;
 148         case SPECIAL_UNSIGNED_GT:
 149                 return SPECIAL_UNSIGNED_LTE;
 150         default:
 151                 sm_perror("unhandled comparison %d", op);
 152                 return op;
 153         }
 154 }
 155 
 156 static int rl_comparison(struct range_list *left_rl, struct range_list *right_rl)
 157 {
 158         sval_t left_min, left_max, right_min, right_max;
 159         struct symbol *type = &int_ctype;
 160 
 161         if (!left_rl || !right_rl)
 162                 return 0;
 163 
 164         if (type_positive_bits(rl_type(left_rl)) > type_positive_bits(type))
 165                 type = rl_type(left_rl);
 166         if (type_positive_bits(rl_type(right_rl)) > type_positive_bits(type))
 167                 type = rl_type(right_rl);
 168 
 169         left_rl = cast_rl(type, left_rl);
 170         right_rl = cast_rl(type, right_rl);
 171 
 172         left_min = rl_min(left_rl);
 173         left_max = rl_max(left_rl);
 174         right_min = rl_min(right_rl);
 175         right_max = rl_max(right_rl);
 176 
 177         if (left_min.value == left_max.value &&
 178             right_min.value == right_max.value &&
 179             left_min.value == right_min.value)
 180                 return SPECIAL_EQUAL;
 181 
 182         if (sval_cmp(left_max, right_min) < 0)
 183                 return '<';
 184         if (sval_cmp(left_max, right_min) == 0)
 185                 return SPECIAL_LTE;
 186         if (sval_cmp(left_min, right_max) > 0)
 187                 return '>';
 188         if (sval_cmp(left_min, right_max) == 0)
 189                 return SPECIAL_GTE;
 190 
 191         return 0;
 192 }
 193 
 194 static int comparison_from_extra(struct expression *a, struct expression *b)
 195 {
 196         struct range_list *left, *right;
 197 
 198         if (!get_implied_rl(a, &left))
 199                 return 0;
 200         if (!get_implied_rl(b, &right))
 201                 return 0;
 202 
 203         return rl_comparison(left, right);
 204 }
 205 
 206 static struct range_list *get_orig_rl(struct var_sym_list *vsl)
 207 {
 208         struct symbol *sym;
 209         struct smatch_state *state;
 210 
 211         if (!vsl)
 212                 return NULL;
 213         sym = vsl_to_sym(vsl);
 214         if (!sym || !sym->ident)
 215                 return NULL;
 216         state = get_orig_estate(sym->ident->name, sym);
 217         return estate_rl(state);
 218 }
 219 
 220 static struct smatch_state *unmatched_comparison(struct sm_state *sm)
 221 {
 222         struct compare_data *data = sm->state->data;
 223         struct range_list *left_rl, *right_rl;
 224         int op;
 225 
 226         if (!data)
 227                 return &undefined;
 228 
 229         if (strstr(data->left_var, " orig"))
 230                 left_rl = get_orig_rl(data->left_vsl);
 231         else if (!get_implied_rl_var_sym(data->left_var, vsl_to_sym(data->left_vsl), &left_rl))
 232                 return &undefined;
 233 
 234         if (strstr(data->right_var, " orig"))
 235                 right_rl = get_orig_rl(data->right_vsl);
 236         else if (!get_implied_rl_var_sym(data->right_var, vsl_to_sym(data->right_vsl), &right_rl))
 237                 return &undefined;
 238 
 239         op = rl_comparison(left_rl, right_rl);
 240         if (op)
 241                 return alloc_compare_state(
 242                                 data->left, data->left_var, data->left_vsl,
 243                                 op,
 244                                 data->right, data->right_var, data->right_vsl);
 245 
 246         return &undefined;
 247 }
 248 
 249 /* remove_unsigned_from_comparison() is obviously a hack. */
 250 int remove_unsigned_from_comparison(int op)
 251 {
 252         switch (op) {
 253         case SPECIAL_UNSIGNED_LT:
 254                 return '<';
 255         case SPECIAL_UNSIGNED_LTE:
 256                 return SPECIAL_LTE;
 257         case SPECIAL_UNSIGNED_GTE:
 258                 return SPECIAL_GTE;
 259         case SPECIAL_UNSIGNED_GT:
 260                 return '>';
 261         default:
 262                 return op;
 263         }
 264 }
 265 
 266 /*
 267  * This is for when you merge states "a < b" and "a == b", the result is that
 268  * we can say for sure, "a <= b" after the merge.
 269  */
 270 int merge_comparisons(int one, int two)
 271 {
 272         int LT, EQ, GT;
 273 
 274         if (!one || !two)
 275                 return 0;
 276 
 277         one = remove_unsigned_from_comparison(one);
 278         two = remove_unsigned_from_comparison(two);
 279 
 280         if (one == two)
 281                 return one;
 282 
 283         LT = EQ = GT = 0;
 284 
 285         switch (one) {
 286         case '<':
 287                 LT = 1;
 288                 break;
 289         case SPECIAL_LTE:
 290                 LT = 1;
 291                 EQ = 1;
 292                 break;
 293         case SPECIAL_EQUAL:
 294                 EQ = 1;
 295                 break;
 296         case SPECIAL_GTE:
 297                 GT = 1;
 298                 EQ = 1;
 299                 break;
 300         case '>':
 301                 GT = 1;
 302         }
 303 
 304         switch (two) {
 305         case '<':
 306                 LT = 1;
 307                 break;
 308         case SPECIAL_LTE:
 309                 LT = 1;
 310                 EQ = 1;
 311                 break;
 312         case SPECIAL_EQUAL:
 313                 EQ = 1;
 314                 break;
 315         case SPECIAL_GTE:
 316                 GT = 1;
 317                 EQ = 1;
 318                 break;
 319         case '>':
 320                 GT = 1;
 321         }
 322 
 323         if (LT && EQ && GT)
 324                 return 0;
 325         if (LT && EQ)
 326                 return SPECIAL_LTE;
 327         if (LT && GT)
 328                 return SPECIAL_NOTEQUAL;
 329         if (LT)
 330                 return '<';
 331         if (EQ && GT)
 332                 return SPECIAL_GTE;
 333         if (GT)
 334                 return '>';
 335         return 0;
 336 }
 337 
 338 /*
 339  * This is for if you have "a < b" and "b <= c".  Or in other words,
 340  * "a < b <= c".  You would call this like get_combined_comparison('<', '<=').
 341  * The return comparison would be '<'.
 342  *
 343  * This function is different from merge_comparisons(), for example:
 344  * merge_comparison('<', '==') returns '<='
 345  * get_combined_comparison('<', '==') returns '<'
 346  */
 347 int combine_comparisons(int left_compare, int right_compare)
 348 {
 349         int LT, EQ, GT;
 350 
 351         left_compare = remove_unsigned_from_comparison(left_compare);
 352         right_compare = remove_unsigned_from_comparison(right_compare);
 353 
 354         LT = EQ = GT = 0;
 355 
 356         switch (left_compare) {
 357         case '<':
 358                 LT++;
 359                 break;
 360         case SPECIAL_LTE:
 361                 LT++;
 362                 EQ++;
 363                 break;
 364         case SPECIAL_EQUAL:
 365                 return right_compare;
 366         case SPECIAL_GTE:
 367                 GT++;
 368                 EQ++;
 369                 break;
 370         case '>':
 371                 GT++;
 372         }
 373 
 374         switch (right_compare) {
 375         case '<':
 376                 LT++;
 377                 break;
 378         case SPECIAL_LTE:
 379                 LT++;
 380                 EQ++;
 381                 break;
 382         case SPECIAL_EQUAL:
 383                 return left_compare;
 384         case SPECIAL_GTE:
 385                 GT++;
 386                 EQ++;
 387                 break;
 388         case '>':
 389                 GT++;
 390         }
 391 
 392         if (LT == 2) {
 393                 if (EQ == 2)
 394                         return SPECIAL_LTE;
 395                 return '<';
 396         }
 397 
 398         if (GT == 2) {
 399                 if (EQ == 2)
 400                         return SPECIAL_GTE;
 401                 return '>';
 402         }
 403         return 0;
 404 }
 405 
 406 int filter_comparison(int orig, int op)
 407 {
 408         if (orig == op)
 409                 return orig;
 410 
 411         orig = remove_unsigned_from_comparison(orig);
 412         op = remove_unsigned_from_comparison(op);
 413 
 414         switch (orig) {
 415         case 0:
 416                 return op;
 417         case '<':
 418                 switch (op) {
 419                 case '<':
 420                 case SPECIAL_LTE:
 421                 case SPECIAL_NOTEQUAL:
 422                         return '<';
 423                 }
 424                 return 0;
 425         case SPECIAL_LTE:
 426                 switch (op) {
 427                 case '<':
 428                 case SPECIAL_LTE:
 429                 case SPECIAL_EQUAL:
 430                         return op;
 431                 case SPECIAL_NOTEQUAL:
 432                         return '<';
 433                 }
 434                 return 0;
 435         case SPECIAL_EQUAL:
 436                 switch (op) {
 437                 case SPECIAL_LTE:
 438                 case SPECIAL_EQUAL:
 439                 case SPECIAL_GTE:
 440                 case SPECIAL_UNSIGNED_LTE:
 441                 case SPECIAL_UNSIGNED_GTE:
 442                         return SPECIAL_EQUAL;
 443                 }
 444                 return 0;
 445         case SPECIAL_NOTEQUAL:
 446                 switch (op) {
 447                 case '<':
 448                 case SPECIAL_LTE:
 449                         return '<';
 450                 case SPECIAL_UNSIGNED_LT:
 451                 case SPECIAL_UNSIGNED_LTE:
 452                         return SPECIAL_UNSIGNED_LT;
 453                 case SPECIAL_NOTEQUAL:
 454                         return op;
 455                 case '>':
 456                 case SPECIAL_GTE:
 457                         return '>';
 458                 case SPECIAL_UNSIGNED_GT:
 459                 case SPECIAL_UNSIGNED_GTE:
 460                         return SPECIAL_UNSIGNED_GT;
 461                 }
 462                 return 0;
 463         case SPECIAL_GTE:
 464                 switch (op) {
 465                 case SPECIAL_LTE:
 466                         return SPECIAL_EQUAL;
 467                 case '>':
 468                 case SPECIAL_GTE:
 469                 case SPECIAL_EQUAL:
 470                         return op;
 471                 case SPECIAL_NOTEQUAL:
 472                         return '>';
 473                 }
 474                 return 0;
 475         case '>':
 476                 switch (op) {
 477                 case '>':
 478                 case SPECIAL_GTE:
 479                 case SPECIAL_NOTEQUAL:
 480                         return '>';
 481                 }
 482                 return 0;
 483         case SPECIAL_UNSIGNED_LT:
 484                 switch (op) {
 485                 case SPECIAL_UNSIGNED_LT:
 486                 case SPECIAL_UNSIGNED_LTE:
 487                 case SPECIAL_NOTEQUAL:
 488                         return SPECIAL_UNSIGNED_LT;
 489                 }
 490                 return 0;
 491         case SPECIAL_UNSIGNED_LTE:
 492                 switch (op) {
 493                 case SPECIAL_UNSIGNED_LT:
 494                 case SPECIAL_UNSIGNED_LTE:
 495                 case SPECIAL_EQUAL:
 496                         return op;
 497                 case SPECIAL_NOTEQUAL:
 498                         return SPECIAL_UNSIGNED_LT;
 499                 case SPECIAL_UNSIGNED_GTE:
 500                         return SPECIAL_EQUAL;
 501                 }
 502                 return 0;
 503         case SPECIAL_UNSIGNED_GTE:
 504                 switch (op) {
 505                 case SPECIAL_UNSIGNED_LTE:
 506                         return SPECIAL_EQUAL;
 507                 case SPECIAL_NOTEQUAL:
 508                         return SPECIAL_UNSIGNED_GT;
 509                 case SPECIAL_EQUAL:
 510                 case SPECIAL_UNSIGNED_GTE:
 511                 case SPECIAL_UNSIGNED_GT:
 512                         return op;
 513                 }
 514                 return 0;
 515         case SPECIAL_UNSIGNED_GT:
 516                 switch (op) {
 517                 case SPECIAL_UNSIGNED_GT:
 518                 case SPECIAL_UNSIGNED_GTE:
 519                 case SPECIAL_NOTEQUAL:
 520                         return SPECIAL_UNSIGNED_GT;
 521                 }
 522                 return 0;
 523         }
 524         return 0;
 525 }
 526 
 527 static void pre_merge_hook(struct sm_state *sm)
 528 {
 529         struct compare_data *data = sm->state->data;
 530         int other;
 531 
 532         if (!data)
 533                 return;
 534         other = get_comparison(data->left, data->right);
 535         if (!other)
 536                 return;
 537 
 538         set_state(compare_id, sm->name, NULL,
 539                   alloc_compare_state(data->left, data->left_var, data->left_vsl,
 540                                       other,
 541                                       data->right, data->right_var, data->right_vsl));
 542 }
 543 
 544 struct smatch_state *merge_compare_states(struct smatch_state *s1, struct smatch_state *s2)
 545 {
 546         struct compare_data *data = s1->data;
 547         int op;
 548 
 549         op = merge_comparisons(state_to_comparison(s1), state_to_comparison(s2));
 550         if (op)
 551                 return alloc_compare_state(
 552                                 data->left, data->left_var, data->left_vsl,
 553                                 op,
 554                                 data->right, data->right_var, data->right_vsl);
 555         return &undefined;
 556 }
 557 
 558 static struct smatch_state *alloc_link_state(struct string_list *links)
 559 {
 560         struct smatch_state *state;
 561         static char buf[256];
 562         char *tmp;
 563         int i;
 564 
 565         state = __alloc_smatch_state(0);
 566 
 567         i = 0;
 568         FOR_EACH_PTR(links, tmp) {
 569                 if (!i++) {
 570                         snprintf(buf, sizeof(buf), "%s", tmp);
 571                 } else {
 572                         append(buf, ", ", sizeof(buf));
 573                         append(buf, tmp, sizeof(buf));
 574                 }
 575         } END_FOR_EACH_PTR(tmp);
 576 
 577         state->name = alloc_sname(buf);
 578         state->data = links;
 579         return state;
 580 }
 581 
 582 static void save_start_states(struct statement *stmt)
 583 {
 584         struct symbol *param;
 585         char orig[64];
 586         char state_name[128];
 587         struct smatch_state *state;
 588         struct string_list *links;
 589         char *link;
 590 
 591         FOR_EACH_PTR(cur_func_sym->ctype.base_type->arguments, param) {
 592                 struct var_sym_list *left_vsl = NULL;
 593                 struct var_sym_list *right_vsl = NULL;
 594 
 595                 if (!param->ident)
 596                         continue;
 597                 snprintf(orig, sizeof(orig), "%s orig", param->ident->name);
 598                 snprintf(state_name, sizeof(state_name), "%s vs %s", param->ident->name, orig);
 599                 add_var_sym(&left_vsl, param->ident->name, param);
 600                 add_var_sym(&right_vsl, orig, param);
 601                 state = alloc_compare_state(
 602                                 NULL, param->ident->name, left_vsl,
 603                                 SPECIAL_EQUAL,
 604                                 NULL, alloc_sname(orig), right_vsl);
 605                 set_state(compare_id, state_name, NULL, state);
 606 
 607                 link = alloc_sname(state_name);
 608                 links = NULL;
 609                 insert_string(&links, link);
 610                 state = alloc_link_state(links);
 611                 set_state(link_id, param->ident->name, param, state);
 612         } END_FOR_EACH_PTR(param);
 613 }
 614 
 615 static struct smatch_state *merge_links(struct smatch_state *s1, struct smatch_state *s2)
 616 {
 617         struct smatch_state *ret;
 618         struct string_list *links;
 619 
 620         links = combine_string_lists(s1->data, s2->data);
 621         ret = alloc_link_state(links);
 622         return ret;
 623 }
 624 
 625 static void save_link_var_sym(const char *var, struct symbol *sym, const char *link)
 626 {
 627         struct smatch_state *old_state, *new_state;
 628         struct string_list *links;
 629         char *new;
 630 
 631         old_state = get_state(link_id, var, sym);
 632         if (old_state)
 633                 links = clone_str_list(old_state->data);
 634         else
 635                 links = NULL;
 636 
 637         new = alloc_sname(link);
 638         insert_string(&links, new);
 639 
 640         new_state = alloc_link_state(links);
 641         set_state(link_id, var, sym, new_state);
 642 }
 643 
 644 static void match_inc(struct sm_state *sm, bool preserve)
 645 {
 646         struct string_list *links;
 647         struct smatch_state *state, *new;
 648         struct compare_data *data;
 649         char *tmp;
 650         int flip;
 651         int op;
 652 
 653         links = sm->state->data;
 654 
 655         FOR_EACH_PTR(links, tmp) {
 656                 state = get_state(compare_id, tmp, NULL);
 657                 if (!state)
 658                         continue;
 659                 data = state->data;
 660                 if (!data)
 661                         continue;
 662 
 663                 flip = 0;
 664                 if (strncmp(sm->name, tmp, strlen(sm->name)) != 0 ||
 665                     tmp[strlen(sm->name)] != ' ')
 666                         flip = 1;
 667 
 668                 op = state_to_comparison(state);
 669 
 670                 switch (flip ? flip_comparison(op) : op) {
 671                 case SPECIAL_EQUAL:
 672                 case SPECIAL_GTE:
 673                 case SPECIAL_UNSIGNED_GTE:
 674                 case '>':
 675                 case SPECIAL_UNSIGNED_GT:
 676                         if (preserve)
 677                                 break;
 678                         new = alloc_compare_state(
 679                                         data->left, data->left_var, data->left_vsl,
 680                                         flip ? '<' : '>',
 681                                         data->right, data->right_var, data->right_vsl);
 682                         set_state(compare_id, tmp, NULL, new);
 683                         break;
 684                 case '<':
 685                 case SPECIAL_UNSIGNED_LT:
 686                         new = alloc_compare_state(
 687                                         data->left, data->left_var, data->left_vsl,
 688                                         flip ? SPECIAL_GTE : SPECIAL_LTE,
 689                                         data->right, data->right_var, data->right_vsl);
 690                         set_state(compare_id, tmp, NULL, new);
 691                         break;
 692                 default:
 693                         set_state(compare_id, tmp, NULL, &undefined);
 694                 }
 695         } END_FOR_EACH_PTR(tmp);
 696 }
 697 
 698 static void match_dec(struct sm_state *sm, bool preserve)
 699 {
 700         struct string_list *links;
 701         struct smatch_state *state;
 702         char *tmp;
 703 
 704         links = sm->state->data;
 705 
 706         FOR_EACH_PTR(links, tmp) {
 707                 state = get_state(compare_id, tmp, NULL);
 708 
 709                 switch (state_to_comparison(state)) {
 710                 case SPECIAL_EQUAL:
 711                 case SPECIAL_LTE:
 712                 case SPECIAL_UNSIGNED_LTE:
 713                 case '<':
 714                 case SPECIAL_UNSIGNED_LT: {
 715                         struct compare_data *data = state->data;
 716                         struct smatch_state *new;
 717 
 718                         if (preserve)
 719                                 break;
 720 
 721                         new = alloc_compare_state(
 722                                         data->left, data->left_var, data->left_vsl,
 723                                         '<',
 724                                         data->right, data->right_var, data->right_vsl);
 725                         set_state(compare_id, tmp, NULL, new);
 726                         break;
 727                         }
 728                 default:
 729                         set_state(compare_id, tmp, NULL, &undefined);
 730                 }
 731         } END_FOR_EACH_PTR(tmp);
 732 }
 733 
 734 static void reset_sm(struct sm_state *sm)
 735 {
 736         struct string_list *links;
 737         char *tmp;
 738 
 739         links = sm->state->data;
 740 
 741         FOR_EACH_PTR(links, tmp) {
 742                 set_state(compare_id, tmp, NULL, &undefined);
 743         } END_FOR_EACH_PTR(tmp);
 744         set_state(link_id, sm->name, sm->sym, &undefined);
 745 }
 746 
 747 static bool match_add_sub_assign(struct sm_state *sm, struct expression *expr)
 748 {
 749         struct range_list *rl;
 750         sval_t zero = { .type = &int_ctype };
 751 
 752         if (!expr || expr->type != EXPR_ASSIGNMENT)
 753                 return false;
 754         if (expr->op != SPECIAL_ADD_ASSIGN && expr->op != SPECIAL_SUB_ASSIGN)
 755                 return false;
 756 
 757         get_absolute_rl(expr->right, &rl);
 758         if (sval_is_negative(rl_min(rl))) {
 759                 reset_sm(sm);
 760                 return false;
 761         }
 762 
 763         if (expr->op == SPECIAL_ADD_ASSIGN)
 764                 match_inc(sm, rl_has_sval(rl, zero));
 765         else
 766                 match_dec(sm, rl_has_sval(rl, zero));
 767         return true;
 768 }
 769 
 770 static void match_inc_dec(struct sm_state *sm, struct expression *mod_expr)
 771 {
 772         /*
 773          * if (foo > bar) then ++foo is also > bar.
 774          */
 775         if (!mod_expr)
 776                 return;
 777         if (match_add_sub_assign(sm, mod_expr))
 778                 return;
 779         if (mod_expr->type != EXPR_PREOP && mod_expr->type != EXPR_POSTOP)
 780                 return;
 781 
 782         if (mod_expr->op == SPECIAL_INCREMENT)
 783                 match_inc(sm, false);
 784         else if (mod_expr->op == SPECIAL_DECREMENT)
 785                 match_dec(sm, false);
 786 }
 787 
 788 static int is_self_assign(struct expression *expr)
 789 {
 790         if (!expr || expr->type != EXPR_ASSIGNMENT || expr->op != '=')
 791                 return 0;
 792         return expr_equiv(expr->left, expr->right);
 793 }
 794 
 795 static void match_modify(struct sm_state *sm, struct expression *mod_expr)
 796 {
 797         if (mod_expr && is_self_assign(mod_expr))
 798                 return;
 799 
 800         /* handled by match_inc_dec() */
 801         if (mod_expr &&
 802             ((mod_expr->type == EXPR_PREOP || mod_expr->type == EXPR_POSTOP) &&
 803              (mod_expr->op == SPECIAL_INCREMENT || mod_expr->op == SPECIAL_DECREMENT)))
 804                 return;
 805         if (mod_expr && mod_expr->type == EXPR_ASSIGNMENT &&
 806             (mod_expr->op == SPECIAL_ADD_ASSIGN || mod_expr->op == SPECIAL_SUB_ASSIGN))
 807                 return;
 808 
 809         reset_sm(sm);
 810 }
 811 
 812 static void match_preop(struct expression *expr)
 813 {
 814         struct expression *parent;
 815         struct range_list *left, *right;
 816         int op;
 817 
 818         /*
 819          * This is an important special case.  Say you have:
 820          *
 821          *      if (++j == limit)
 822          *
 823          * Assume that we know the range of limit is higher than the start
 824          * value for "j".  Then the first thing that we process is the ++j.  We
 825          * have not comparison states set up so it doesn't get caught by the
 826          * modification hook.  But it does get caught by smatch_extra which sets
 827          * j to unknown then we parse the "j == limit" and sets false to != but
 828          * really we want false to be <.
 829          *
 830          * So what we do is we set j < limit here, then the match_modify catches
 831          * it and we do a match_inc_dec().
 832          *
 833          */
 834 
 835         if (expr->type != EXPR_PREOP ||
 836             (expr->op != SPECIAL_INCREMENT && expr->op != SPECIAL_DECREMENT))
 837                 return;
 838 
 839         parent = expr_get_parent_expr(expr);
 840         if (!parent)
 841                 return;
 842         if (parent->type != EXPR_COMPARE || parent->op != SPECIAL_EQUAL)
 843                 return;
 844         if (parent->left != expr)
 845                 return;
 846 
 847         if (!get_implied_rl(expr->unop, &left) ||
 848            !get_implied_rl(parent->right, &right))
 849                 return;
 850 
 851         op = rl_comparison(left, right);
 852         if (!op)
 853                 return;
 854 
 855         add_comparison(expr->unop, op, parent->right);
 856 }
 857 
 858 static char *chunk_to_var_sym(struct expression *expr, struct symbol **sym)
 859 {
 860         expr = strip_expr(expr);
 861         if (!expr)
 862                 return NULL;
 863         if (sym)
 864                 *sym = NULL;
 865 
 866         if (expr->type == EXPR_PREOP &&
 867             (expr->op == SPECIAL_INCREMENT ||
 868              expr->op == SPECIAL_DECREMENT))
 869                 expr = strip_expr(expr->unop);
 870 
 871         if (expr->type == EXPR_CALL) {
 872                 char buf[64];
 873 
 874                 snprintf(buf, sizeof(buf), "return %p", expr);
 875                 return alloc_string(buf);
 876         }
 877 
 878         return expr_to_chunk_sym_vsl(expr, sym, NULL);
 879 }
 880 
 881 static char *chunk_to_var(struct expression *expr)
 882 {
 883         return chunk_to_var_sym(expr, NULL);
 884 }
 885 
 886 static struct smatch_state *get_state_chunk(int owner, struct expression *expr)
 887 {
 888         char *name;
 889         struct symbol *sym;
 890         struct smatch_state *ret;
 891 
 892         name = chunk_to_var_sym(expr, &sym);
 893         if (!name)
 894                 return NULL;
 895 
 896         ret = get_state(owner, name, sym);
 897         free_string(name);
 898         return ret;
 899 }
 900 
 901 static void save_link(struct expression *expr, char *link)
 902 {
 903         char *var;
 904         struct symbol *sym;
 905 
 906         expr = strip_expr(expr);
 907         if (expr->type == EXPR_BINOP) {
 908                 char *chunk;
 909 
 910                 chunk = chunk_to_var(expr);
 911                 if (!chunk)
 912                         return;
 913 
 914                 save_link(expr->left, link);
 915                 save_link(expr->right, link);
 916                 save_link_var_sym(chunk, NULL, link);
 917                 return;
 918         }
 919 
 920         var = chunk_to_var_sym(expr, &sym);
 921         if (!var)
 922                 return;
 923 
 924         save_link_var_sym(var, sym, link);
 925         free_string(var);
 926 }
 927 
 928 static int get_orig_comparison(struct stree *pre_stree, const char *left, const char *right)
 929 {
 930         struct smatch_state *state;
 931         struct compare_data *data;
 932         int flip = 0;
 933         char state_name[256];
 934 
 935         if (strcmp(left, right) > 0) {
 936                 const char *tmp = right;
 937 
 938                 flip = 1;
 939                 right = left;
 940                 left = tmp;
 941         }
 942 
 943         snprintf(state_name, sizeof(state_name), "%s vs %s", left, right);
 944         state = get_state_stree(pre_stree, compare_id, state_name, NULL);
 945         if (!state || !state->data)
 946                 return 0;
 947         data = state->data;
 948         if (flip)
 949                 return flip_comparison(data->comparison);
 950         return data->comparison;
 951 
 952 }
 953 
 954 static int have_common_var_sym(struct var_sym_list *left_vsl, struct var_sym_list *right_vsl)
 955 {
 956         struct var_sym *tmp;
 957 
 958         FOR_EACH_PTR(left_vsl, tmp) {
 959                 if (in_var_sym_list(right_vsl, tmp->var, tmp->sym))
 960                         return 1;
 961         } END_FOR_EACH_PTR(tmp);
 962 
 963         return 0;
 964 }
 965 
 966 /*
 967  * The idea here is that we take a comparison "a < b" and then we look at all
 968  * the things which "b" is compared against "b < c" and we say that that implies
 969  * a relationship "a < c".
 970  *
 971  * The names here about because the comparisons are organized like this
 972  * "a < b < c".
 973  *
 974  */
 975 static void update_tf_links(struct stree *pre_stree,
 976                             struct expression *left_expr,
 977                             const char *left_var, struct var_sym_list *left_vsl,
 978                             int left_comparison, int left_false_comparison,
 979                             const char *mid_var, struct var_sym_list *mid_vsl,
 980                             struct string_list *links)
 981 {
 982         struct smatch_state *state;
 983         struct smatch_state *true_state, *false_state;
 984         struct compare_data *data;
 985         struct expression *right_expr;
 986         const char *right_var;
 987         struct var_sym_list *right_vsl;
 988         int orig_comparison;
 989         int right_comparison;
 990         int true_comparison;
 991         int false_comparison;
 992         char *tmp;
 993         char state_name[256];
 994         struct var_sym *vs;
 995 
 996         FOR_EACH_PTR(links, tmp) {
 997                 state = get_state_stree(pre_stree, compare_id, tmp, NULL);
 998                 if (!state || !state->data)
 999                         continue;
1000                 data = state->data;
1001                 right_comparison = data->comparison;
1002                 right_expr = data->right;
1003                 right_var = data->right_var;
1004                 right_vsl = data->right_vsl;
1005                 if (strcmp(mid_var, right_var) == 0) {
1006                         right_expr = data->left;
1007                         right_var = data->left_var;
1008                         right_vsl = data->left_vsl;
1009                         right_comparison = flip_comparison(right_comparison);
1010                 }
1011                 if (have_common_var_sym(left_vsl, right_vsl))
1012                         continue;
1013 
1014                 orig_comparison = get_orig_comparison(pre_stree, left_var, right_var);
1015 
1016                 true_comparison = combine_comparisons(left_comparison, right_comparison);
1017                 false_comparison = combine_comparisons(left_false_comparison, right_comparison);
1018 
1019                 true_comparison = filter_comparison(orig_comparison, true_comparison);
1020                 false_comparison = filter_comparison(orig_comparison, false_comparison);
1021 
1022                 if (strcmp(left_var, right_var) > 0) {
1023                         struct expression *tmp_expr = left_expr;
1024                         const char *tmp_var = left_var;
1025                         struct var_sym_list *tmp_vsl = left_vsl;
1026 
1027                         left_expr = right_expr;
1028                         left_var = right_var;
1029                         left_vsl = right_vsl;
1030                         right_expr = tmp_expr;
1031                         right_var = tmp_var;
1032                         right_vsl = tmp_vsl;
1033                         true_comparison = flip_comparison(true_comparison);
1034                         false_comparison = flip_comparison(false_comparison);
1035                 }
1036 
1037                 if (!true_comparison && !false_comparison)
1038                         continue;
1039 
1040                 if (true_comparison)
1041                         true_state = alloc_compare_state(
1042                                         left_expr, left_var, left_vsl,
1043                                         true_comparison,
1044                                         right_expr, right_var, right_vsl);
1045                 else
1046                         true_state = NULL;
1047                 if (false_comparison)
1048                         false_state = alloc_compare_state(
1049                                         left_expr, left_var, left_vsl,
1050                                         false_comparison,
1051                                         right_expr, right_var, right_vsl);
1052                 else
1053                         false_state = NULL;
1054 
1055                 snprintf(state_name, sizeof(state_name), "%s vs %s", left_var, right_var);
1056                 set_true_false_states(compare_id, state_name, NULL, true_state, false_state);
1057                 FOR_EACH_PTR(left_vsl, vs) {
1058                         save_link_var_sym(vs->var, vs->sym, state_name);
1059                 } END_FOR_EACH_PTR(vs);
1060                 FOR_EACH_PTR(right_vsl, vs) {
1061                         save_link_var_sym(vs->var, vs->sym, state_name);
1062                 } END_FOR_EACH_PTR(vs);
1063                 if (!vsl_to_sym(left_vsl))
1064                         save_link_var_sym(left_var, NULL, state_name);
1065                 if (!vsl_to_sym(right_vsl))
1066                         save_link_var_sym(right_var, NULL, state_name);
1067         } END_FOR_EACH_PTR(tmp);
1068 }
1069 
1070 static void update_tf_data(struct stree *pre_stree,
1071                 struct expression *left_expr,
1072                 const char *left_name, struct var_sym_list *left_vsl,
1073                 struct expression *right_expr,
1074                 const char *right_name, struct var_sym_list *right_vsl,
1075                 int true_comparison, int false_comparison)
1076 {
1077         struct smatch_state *state;
1078 
1079         state = get_state_stree(pre_stree, link_id, right_name, vsl_to_sym(right_vsl));
1080         if (state)
1081                 update_tf_links(pre_stree, left_expr, left_name, left_vsl, true_comparison, false_comparison, right_name, right_vsl, state->data);
1082 
1083         state = get_state_stree(pre_stree, link_id, left_name, vsl_to_sym(left_vsl));
1084         if (state)
1085                 update_tf_links(pre_stree, right_expr, right_name, right_vsl, flip_comparison(true_comparison), flip_comparison(false_comparison), left_name, left_vsl, state->data);
1086 }
1087 
1088 static void iter_modify(struct sm_state *sm, struct expression *mod_expr)
1089 {
1090         if (sm->state != &start ||
1091             !mod_expr ||
1092             (mod_expr->type != EXPR_PREOP && mod_expr->type != EXPR_POSTOP) ||
1093             mod_expr->op != SPECIAL_INCREMENT)
1094                 set_state(inc_dec_id, sm->name, sm->sym, &undefined);
1095         else
1096                 set_state(inc_dec_id, sm->name, sm->sym, &incremented);
1097 }
1098 
1099 static void handle_for_loops(struct expression *expr, char *state_name, struct smatch_state *false_state)
1100 {
1101         sval_t sval;
1102         char *iter_name, *cap_name;
1103         struct symbol *iter_sym, *cap_sym;
1104         struct compare_data *data;
1105 
1106         if (expr->op != '<' && expr->op != SPECIAL_UNSIGNED_LT)
1107                 return;
1108 
1109         if (!__cur_stmt || !__prev_stmt)
1110                 return;
1111         if (__cur_stmt->type != STMT_ITERATOR)
1112                 return;
1113         if (__cur_stmt->iterator_pre_condition != expr)
1114                 return;
1115 
1116         /* literals are handled in smatch_extra.c */
1117         if (get_value(expr->right, &sval))
1118                 return;
1119 
1120         /* First time checking the condition */
1121         if (__prev_stmt == __cur_stmt->iterator_pre_statement) {
1122                 if (!get_implied_value(expr->left, &sval) ||
1123                     sval.value != 0)
1124                         return;
1125 
1126                 iter_name = expr_to_var_sym(expr->left, &iter_sym);
1127                 cap_name = expr_to_var_sym(expr->right, &cap_sym);
1128                 if (!iter_name || !cap_name || !iter_sym || !cap_sym) {
1129                         free_string(iter_name);
1130                         free_string(cap_name);
1131                         return;
1132                 }
1133 
1134                 set_state(inc_dec_id, iter_name, iter_sym, &start);
1135                 store_link(inc_dec_link_id, cap_name, cap_sym, iter_name, iter_sym);
1136 
1137                 free_string(iter_name);
1138                 free_string(cap_name);
1139                 return;
1140         }
1141 
1142         /* Second time checking the condtion */
1143         if (__prev_stmt != __cur_stmt->iterator_post_statement)
1144                 return;
1145 
1146         if (get_state_chunk(inc_dec_id, expr->left) != &incremented)
1147                 return;
1148 
1149         data = false_state->data;
1150         false_state = alloc_compare_state(
1151                         data->left, data->left_var, data->left_vsl,
1152                         SPECIAL_EQUAL,
1153                         data->right, data->right_var, data->right_vsl);
1154 
1155         set_true_false_states(compare_id, state_name, NULL, NULL, false_state);
1156 }
1157 
1158 static int is_plus_one(struct expression *expr)
1159 {
1160         sval_t sval;
1161 
1162         if (expr->type != EXPR_BINOP || expr->op != '+')
1163                 return 0;
1164         if (!get_implied_value(expr->right, &sval) || sval.value != 1)
1165                 return 0;
1166         return 1;
1167 }
1168 
1169 static int is_minus_one(struct expression *expr)
1170 {
1171         sval_t sval;
1172 
1173         if (expr->type != EXPR_BINOP || expr->op != '-')
1174                 return 0;
1175         if (!get_implied_value(expr->right, &sval) || sval.value != 1)
1176                 return 0;
1177         return 1;
1178 }
1179 
1180 static void move_plus_to_minus_helper(struct expression **left_p, struct expression **right_p)
1181 {
1182         struct expression *left = *left_p;
1183         struct expression *right = *right_p;
1184 
1185         /*
1186          * These two are basically equivalent: "foo + 1 != bar" and
1187          * "foo != bar - 1".  There are issues with signedness and integer
1188          * overflows.  There are also issues with type as well.  But let's
1189          * pretend we can ignore all that stuff for now.
1190          *
1191          */
1192 
1193         if (!is_plus_one(left))
1194                 return;
1195 
1196         *left_p = left->left;
1197         *right_p = binop_expression(right, '-', left->right);
1198 }
1199 
1200 static void move_plus_to_minus(struct expression **left_p, struct expression **right_p)
1201 {
1202         if (is_plus_one(*left_p) && is_plus_one(*right_p))
1203                 return;
1204 
1205         move_plus_to_minus_helper(left_p, right_p);
1206         move_plus_to_minus_helper(right_p, left_p);
1207 }
1208 
1209 static void handle_comparison(struct expression *left_expr, int op, struct expression *right_expr, char **_state_name, struct smatch_state **_false_state)
1210 {
1211         char *left = NULL;
1212         char *right = NULL;
1213         struct symbol *left_sym, *right_sym;
1214         struct var_sym_list *left_vsl = NULL;
1215         struct var_sym_list *right_vsl = NULL;
1216         int false_op;
1217         int orig_comparison;
1218         struct smatch_state *true_state, *false_state;
1219         static char state_name[256];
1220         struct stree *pre_stree;
1221         sval_t sval;
1222 
1223         if (!left_expr || !right_expr)
1224                 return;
1225 
1226         left_expr = strip_parens(left_expr);
1227         right_expr = strip_parens(right_expr);
1228 
1229         while (left_expr->type == EXPR_ASSIGNMENT)
1230                 left_expr = strip_parens(left_expr->left);
1231         while (right_expr->type == EXPR_ASSIGNMENT)
1232                 right_expr = strip_parens(right_expr->left);
1233 
1234         false_op = negate_comparison(op);
1235 
1236         move_plus_to_minus(&left_expr, &right_expr);
1237 
1238         if (op == SPECIAL_UNSIGNED_LT &&
1239             get_implied_value(left_expr, &sval) &&
1240             sval.value == 0)
1241                 false_op = SPECIAL_EQUAL;
1242 
1243         if (op == SPECIAL_UNSIGNED_GT &&
1244             get_implied_value(right_expr, &sval) &&
1245             sval.value == 0)
1246                 false_op = SPECIAL_EQUAL;
1247 
1248         left = chunk_to_var_sym(left_expr, &left_sym);
1249         if (!left)
1250                 goto free;
1251         if (left_sym)
1252                 add_var_sym(&left_vsl, left, left_sym);
1253         else
1254                 left_vsl = expr_to_vsl(left_expr);
1255         right = chunk_to_var_sym(right_expr, &right_sym);
1256         if (!right)
1257                 goto free;
1258         if (right_sym)
1259                 add_var_sym(&right_vsl, right, right_sym);
1260         else
1261                 right_vsl = expr_to_vsl(right_expr);
1262 
1263         if (strcmp(left, right) > 0) {
1264                 char *tmp_name = left;
1265                 struct var_sym_list *tmp_vsl = left_vsl;
1266                 struct expression *tmp_expr = left_expr;
1267 
1268                 left = right;
1269                 left_vsl = right_vsl;
1270                 left_expr = right_expr;
1271                 right = tmp_name;
1272                 right_vsl = tmp_vsl;
1273                 right_expr = tmp_expr;
1274                 op = flip_comparison(op);
1275                 false_op = flip_comparison(false_op);
1276         }
1277 
1278         orig_comparison = get_comparison(left_expr, right_expr);
1279         op = filter_comparison(orig_comparison, op);
1280         false_op = filter_comparison(orig_comparison, false_op);
1281 
1282         snprintf(state_name, sizeof(state_name), "%s vs %s", left, right);
1283         true_state = alloc_compare_state(
1284                         left_expr, left, left_vsl,
1285                         op,
1286                         right_expr, right, right_vsl);
1287         false_state = alloc_compare_state(
1288                         left_expr, left, left_vsl,
1289                         false_op,
1290                         right_expr, right, right_vsl);
1291 
1292         pre_stree = clone_stree(__get_cur_stree());
1293         update_tf_data(pre_stree, left_expr, left, left_vsl, right_expr, right, right_vsl, op, false_op);
1294         free_stree(&pre_stree);
1295 
1296         set_true_false_states(compare_id, state_name, NULL, true_state, false_state);
1297         __compare_param_limit_hook(left_expr, right_expr, state_name, true_state, false_state);
1298         save_link(left_expr, state_name);
1299         save_link(right_expr, state_name);
1300 
1301         if (_false_state)
1302                 *_false_state = false_state;
1303         if (_state_name)
1304                 *_state_name = state_name;
1305 free:
1306         free_string(left);
1307         free_string(right);
1308 }
1309 
1310 void __comparison_match_condition(struct expression *expr)
1311 {
1312         struct expression *left, *right, *new_left, *new_right, *tmp;
1313         struct smatch_state *false_state = NULL;
1314         char *state_name = NULL;
1315         int redo, count;
1316 
1317         if (expr->type != EXPR_COMPARE)
1318                 return;
1319 
1320         handle_comparison(expr->left, expr->op, expr->right, &state_name, &false_state);
1321         if (false_state && state_name)
1322                 handle_for_loops(expr, state_name, false_state);
1323 
1324         left = strip_parens(expr->left);
1325         right = strip_parens(expr->right);
1326 
1327         if (left->type == EXPR_BINOP && left->op == '+') {
1328                 new_left = left->left;
1329                 new_right = binop_expression(right, '-', left->right);
1330                 handle_comparison(new_left, expr->op, new_right, NULL, NULL);
1331 
1332                 new_left = left->right;
1333                 new_right = binop_expression(right, '-', left->left);
1334                 handle_comparison(new_left, expr->op, new_right, NULL, NULL);
1335         }
1336 
1337 
1338         redo = 0;
1339         left = strip_parens(expr->left);
1340         right = strip_parens(expr->right);
1341         if (get_last_expr_from_expression_stmt(expr->left)) {
1342                 left = get_last_expr_from_expression_stmt(expr->left);
1343                 redo = 1;
1344         }
1345         if (get_last_expr_from_expression_stmt(expr->right)) {
1346                 right = get_last_expr_from_expression_stmt(expr->right);
1347                 redo = 1;
1348         }
1349 
1350         if (!redo)
1351                 return;
1352 
1353         count = 0;
1354         while ((tmp = get_assigned_expr(left))) {
1355                 if (count++ > 3)
1356                         break;
1357                 left = strip_expr(tmp);
1358         }
1359         count = 0;
1360         while ((tmp = get_assigned_expr(right))) {
1361                 if (count++ > 3)
1362                         break;
1363                 right = strip_expr(tmp);
1364         }
1365 
1366         handle_comparison(left, expr->op, right, NULL, NULL);
1367 }
1368 
1369 static void add_comparison_var_sym(
1370                 struct expression *left_expr,
1371                 const char *left_name, struct var_sym_list *left_vsl,
1372                 int comparison,
1373                 struct expression *right_expr,
1374                 const char *right_name, struct var_sym_list *right_vsl)
1375 {
1376         struct smatch_state *state;
1377         struct var_sym *vs;
1378         char state_name[256];
1379 
1380         if (strcmp(left_name, right_name) > 0) {
1381                 struct expression *tmp_expr = left_expr;
1382                 const char *tmp_name = left_name;
1383                 struct var_sym_list *tmp_vsl = left_vsl;
1384 
1385                 left_expr = right_expr;
1386                 left_name = right_name;
1387                 left_vsl = right_vsl;
1388                 right_expr = tmp_expr;
1389                 right_name = tmp_name;
1390                 right_vsl = tmp_vsl;
1391                 comparison = flip_comparison(comparison);
1392         }
1393         snprintf(state_name, sizeof(state_name), "%s vs %s", left_name, right_name);
1394         state = alloc_compare_state(
1395                         left_expr, left_name, left_vsl,
1396                         comparison,
1397                         right_expr, right_name, right_vsl);
1398 
1399         set_state(compare_id, state_name, NULL, state);
1400 
1401         FOR_EACH_PTR(left_vsl, vs) {
1402                 save_link_var_sym(vs->var, vs->sym, state_name);
1403         } END_FOR_EACH_PTR(vs);
1404         FOR_EACH_PTR(right_vsl, vs) {
1405                 save_link_var_sym(vs->var, vs->sym, state_name);
1406         } END_FOR_EACH_PTR(vs);
1407 }
1408 
1409 static void add_comparison(struct expression *left, int comparison, struct expression *right)
1410 {
1411         char *left_name = NULL;
1412         char *right_name = NULL;
1413         struct symbol *left_sym, *right_sym;
1414         struct var_sym_list *left_vsl, *right_vsl;
1415         struct smatch_state *state;
1416         char state_name[256];
1417 
1418         left_name = chunk_to_var_sym(left, &left_sym);
1419         if (!left_name)
1420                 goto free;
1421         left_vsl = expr_to_vsl(left);
1422         right_name = chunk_to_var_sym(right, &right_sym);
1423         if (!right_name)
1424                 goto free;
1425         right_vsl = expr_to_vsl(right);
1426 
1427         if (strcmp(left_name, right_name) > 0) {
1428                 struct expression *tmp_expr = left;
1429                 struct symbol *tmp_sym = left_sym;
1430                 char *tmp_name = left_name;
1431                 struct var_sym_list *tmp_vsl = left_vsl;
1432 
1433                 left = right;
1434                 left_name = right_name;
1435                 left_sym = right_sym;
1436                 left_vsl = right_vsl;
1437                 right = tmp_expr;
1438                 right_name = tmp_name;
1439                 right_sym = tmp_sym;
1440                 right_vsl = tmp_vsl;
1441                 comparison = flip_comparison(comparison);
1442         }
1443         snprintf(state_name, sizeof(state_name), "%s vs %s", left_name, right_name);
1444         state = alloc_compare_state(
1445                         left, left_name, left_vsl,
1446                         comparison,
1447                         right, right_name, right_vsl);
1448 
1449         set_state(compare_id, state_name, NULL, state);
1450         save_link(left, state_name);
1451         save_link(right, state_name);
1452 
1453 free:
1454         free_string(left_name);
1455         free_string(right_name);
1456 }
1457 
1458 static void match_assign_add(struct expression *expr)
1459 {
1460         struct expression *right;
1461         struct expression *r_left, *r_right;
1462         sval_t left_tmp, right_tmp;
1463 
1464         right = strip_expr(expr->right);
1465         r_left = strip_expr(right->left);
1466         r_right = strip_expr(right->right);
1467 
1468         get_absolute_min(r_left, &left_tmp);
1469         get_absolute_min(r_right, &right_tmp);
1470 
1471         if (left_tmp.value > 0)
1472                 add_comparison(expr->left, '>', r_right);
1473         else if (left_tmp.value == 0)
1474                 add_comparison(expr->left, SPECIAL_GTE, r_right);
1475 
1476         if (right_tmp.value > 0)
1477                 add_comparison(expr->left, '>', r_left);
1478         else if (right_tmp.value == 0)
1479                 add_comparison(expr->left, SPECIAL_GTE, r_left);
1480 }
1481 
1482 static void match_assign_sub(struct expression *expr)
1483 {
1484         struct expression *right;
1485         struct expression *r_left, *r_right;
1486         int comparison;
1487         sval_t min;
1488 
1489         right = strip_expr(expr->right);
1490         r_left = strip_expr(right->left);
1491         r_right = strip_expr(right->right);
1492 
1493         if (get_absolute_min(r_right, &min) && sval_is_negative(min))
1494                 return;
1495 
1496         comparison = get_comparison(r_left, r_right);
1497 
1498         switch (comparison) {
1499         case '>':
1500         case SPECIAL_GTE:
1501                 if (implied_not_equal(r_right, 0))
1502                         add_comparison(expr->left, '>', r_left);
1503                 else
1504                         add_comparison(expr->left, SPECIAL_GTE, r_left);
1505                 return;
1506         }
1507 }
1508 
1509 static void match_assign_divide(struct expression *expr)
1510 {
1511         struct expression *right;
1512         struct expression *r_left, *r_right;
1513         sval_t min;
1514 
1515         right = strip_expr(expr->right);
1516         r_left = strip_expr(right->left);
1517         r_right = strip_expr(right->right);
1518         if (!get_implied_min(r_right, &min) || min.value <= 1)
1519                 return;
1520 
1521         add_comparison(expr->left, '<', r_left);
1522 }
1523 
1524 static void match_binop_assign(struct expression *expr)
1525 {
1526         struct expression *right;
1527 
1528         right = strip_expr(expr->right);
1529         if (right->op == '+')
1530                 match_assign_add(expr);
1531         if (right->op == '-')
1532                 match_assign_sub(expr);
1533         if (right->op == '/')
1534                 match_assign_divide(expr);
1535 }
1536 
1537 static void copy_comparisons(struct expression *left, struct expression *right)
1538 {
1539         struct string_list *links;
1540         struct smatch_state *state;
1541         struct compare_data *data;
1542         struct symbol *left_sym, *right_sym;
1543         char *left_var = NULL;
1544         char *right_var = NULL;
1545         struct var_sym_list *left_vsl;
1546         struct expression *expr;
1547         const char *var;
1548         struct var_sym_list *vsl;
1549         int comparison;
1550         char *tmp;
1551 
1552         left_var = chunk_to_var_sym(left, &left_sym);
1553         if (!left_var)
1554                 goto done;
1555         left_vsl = expr_to_vsl(left);
1556         right_var = chunk_to_var_sym(right, &right_sym);
1557         if (!right_var)
1558                 goto done;
1559 
1560         state = get_state(link_id, right_var, right_sym);
1561         if (!state)
1562                 return;
1563         links = state->data;
1564 
1565         FOR_EACH_PTR(links, tmp) {
1566                 state = get_state(compare_id, tmp, NULL);
1567                 if (!state || !state->data)
1568                         continue;
1569                 data = state->data;
1570                 comparison = data->comparison;
1571                 expr = data->right;
1572                 var = data->right_var;
1573                 vsl = data->right_vsl;
1574                 if (strcmp(var, right_var) == 0) {
1575                         expr = data->left;
1576                         var = data->left_var;
1577                         vsl = data->left_vsl;
1578                         comparison = flip_comparison(comparison);
1579                 }
1580                 /* n = copy_from_user(dest, src, n); leads to n <= n which is nonsense */
1581                 if (strcmp(left_var, var) == 0)
1582                         continue;
1583                 add_comparison_var_sym(left, left_var, left_vsl, comparison, expr, var, vsl);
1584         } END_FOR_EACH_PTR(tmp);
1585 
1586 done:
1587         free_string(right_var);
1588 }
1589 
1590 static void match_assign(struct expression *expr)
1591 {
1592         struct expression *right;
1593 
1594         if (expr->op != '=')
1595                 return;
1596         if (__in_fake_assign || outside_of_function())
1597                 return;
1598 
1599         if (is_struct(expr->left))
1600                 return;
1601 
1602         if (is_self_assign(expr))
1603                 return;
1604 
1605         copy_comparisons(expr->left, expr->right);
1606         add_comparison(expr->left, SPECIAL_EQUAL, expr->right);
1607 
1608         right = strip_expr(expr->right);
1609         if (right->type == EXPR_BINOP)
1610                 match_binop_assign(expr);
1611 }
1612 
1613 int get_comparison_strings(const char *one, const char *two)
1614 {
1615         char buf[256];
1616         struct smatch_state *state;
1617         int invert = 0;
1618         int ret = 0;
1619 
1620         if (!one || !two)
1621                 return 0;
1622 
1623         if (strcmp(one, two) == 0)
1624                 return SPECIAL_EQUAL;
1625 
1626         if (strcmp(one, two) > 0) {
1627                 const char *tmp = one;
1628 
1629                 one = two;
1630                 two = tmp;
1631                 invert = 1;
1632         }
1633 
1634         snprintf(buf, sizeof(buf), "%s vs %s", one, two);
1635         state = get_state(compare_id, buf, NULL);
1636         if (state)
1637                 ret = state_to_comparison(state);
1638 
1639         if (invert)
1640                 ret = flip_comparison(ret);
1641 
1642         return ret;
1643 }
1644 
1645 static int get_comparison_helper(struct expression *a, struct expression *b, bool use_extra)
1646 {
1647         char *one = NULL;
1648         char *two = NULL;
1649         int ret = 0;
1650 
1651         if (!a || !b)
1652                 return 0;
1653 
1654         a = strip_parens(a);
1655         b = strip_parens(b);
1656 
1657         move_plus_to_minus(&a, &b);
1658 
1659         one = chunk_to_var(a);
1660         if (!one)
1661                 goto free;
1662         two = chunk_to_var(b);
1663         if (!two)
1664                 goto free;
1665 
1666         ret = get_comparison_strings(one, two);
1667         if (ret)
1668                 goto free;
1669 
1670         if (is_plus_one(a) || is_minus_one(a)) {
1671                 free_string(one);
1672                 one = chunk_to_var(a->left);
1673                 ret = get_comparison_strings(one, two);
1674         } else if (is_plus_one(b) || is_minus_one(b)) {
1675                 free_string(two);
1676                 two = chunk_to_var(b->left);
1677                 ret = get_comparison_strings(one, two);
1678         }
1679 
1680         if (!ret)
1681                 goto free;
1682 
1683         if ((is_plus_one(a) || is_minus_one(b)) && ret == '<')
1684                 ret = SPECIAL_LTE;
1685         else if ((is_minus_one(a) || is_plus_one(b)) && ret == '>')
1686                 ret = SPECIAL_GTE;
1687         else
1688                 ret = 0;
1689 
1690 free:
1691         free_string(one);
1692         free_string(two);
1693 
1694         if (!ret && use_extra)
1695                 return comparison_from_extra(a, b);
1696         return ret;
1697 }
1698 
1699 int get_comparison(struct expression *a, struct expression *b)
1700 {
1701         return get_comparison_helper(a, b, true);
1702 }
1703 
1704 int get_comparison_no_extra(struct expression *a, struct expression *b)
1705 {
1706         return get_comparison_helper(a, b, false);
1707 }
1708 
1709 int possible_comparison(struct expression *a, int comparison, struct expression *b)
1710 {
1711         char *one = NULL;
1712         char *two = NULL;
1713         int ret = 0;
1714         char buf[256];
1715         struct sm_state *sm;
1716         int saved;
1717 
1718         one = chunk_to_var(a);
1719         if (!one)
1720                 goto free;
1721         two = chunk_to_var(b);
1722         if (!two)
1723                 goto free;
1724 
1725 
1726         if (strcmp(one, two) == 0 && comparison == SPECIAL_EQUAL) {
1727                 ret = 1;
1728                 goto free;
1729         }
1730 
1731         if (strcmp(one, two) > 0) {
1732                 char *tmp = one;
1733 
1734                 one = two;
1735                 two = tmp;
1736                 comparison = flip_comparison(comparison);
1737         }
1738 
1739         snprintf(buf, sizeof(buf), "%s vs %s", one, two);
1740         sm = get_sm_state(compare_id, buf, NULL);
1741         if (!sm)
1742                 goto free;
1743 
1744         FOR_EACH_PTR(sm->possible, sm) {
1745                 if (!sm->state->data)
1746                         continue;
1747                 saved = ((struct compare_data *)sm->state->data)->comparison;
1748                 if (saved == comparison)
1749                         ret = 1;
1750                 if (comparison == SPECIAL_EQUAL &&
1751                     (saved == SPECIAL_LTE ||
1752                      saved == SPECIAL_GTE ||
1753                      saved == SPECIAL_UNSIGNED_LTE ||
1754                      saved == SPECIAL_UNSIGNED_GTE))
1755                         ret = 1;
1756                 if (ret == 1)
1757                         goto free;
1758         } END_FOR_EACH_PTR(sm);
1759 
1760         return ret;
1761 free:
1762         free_string(one);
1763         free_string(two);
1764         return ret;
1765 }
1766 
1767 struct state_list *get_all_comparisons(struct expression *expr)
1768 {
1769         struct smatch_state *state;
1770         struct string_list *links;
1771         struct state_list *ret = NULL;
1772         struct sm_state *sm;
1773         char *tmp;
1774 
1775         state = get_state_chunk(link_id, expr);
1776         if (!state)
1777                 return NULL;
1778         links = state->data;
1779 
1780         FOR_EACH_PTR(links, tmp) {
1781                 sm = get_sm_state(compare_id, tmp, NULL);
1782                 if (!sm)
1783                         continue;
1784                 // FIXME have to compare name with vsl
1785                 add_ptr_list(&ret, sm);
1786         } END_FOR_EACH_PTR(tmp);
1787 
1788         return ret;
1789 }
1790 
1791 struct state_list *get_all_possible_equal_comparisons(struct expression *expr)
1792 {
1793         struct smatch_state *state;
1794         struct string_list *links;
1795         struct state_list *ret = NULL;
1796         struct sm_state *sm;
1797         char *tmp;
1798 
1799         state = get_state_chunk(link_id, expr);
1800         if (!state)
1801                 return NULL;
1802         links = state->data;
1803 
1804         FOR_EACH_PTR(links, tmp) {
1805                 sm = get_sm_state(compare_id, tmp, NULL);
1806                 if (!sm)
1807                         continue;
1808                 if (!strchr(sm->state->name, '='))
1809                         continue;
1810                 if (strcmp(sm->state->name, "!=") == 0)
1811                         continue;
1812                 add_ptr_list(&ret, sm);
1813         } END_FOR_EACH_PTR(tmp);
1814 
1815         return ret;
1816 }
1817 
1818 struct state_list *get_all_possible_not_equal_comparisons(struct expression *expr)
1819 {
1820         struct smatch_state *state;
1821         struct string_list *links;
1822         struct state_list *ret = NULL;
1823         struct sm_state *sm;
1824         struct sm_state *possible;
1825         char *link;
1826 
1827         return NULL;
1828 
1829         state = get_state_chunk(link_id, expr);
1830         if (!state)
1831                 return NULL;
1832         links = state->data;
1833 
1834         FOR_EACH_PTR(links, link) {
1835                 sm = get_sm_state(compare_id, link, NULL);
1836                 if (!sm)
1837                         continue;
1838                 FOR_EACH_PTR(sm->possible, possible) {
1839                         if (strcmp(possible->state->name, "!=") != 0)
1840                                 continue;
1841                         add_ptr_list(&ret, sm);
1842                         break;
1843                 } END_FOR_EACH_PTR(link);
1844         } END_FOR_EACH_PTR(link);
1845 
1846         return ret;
1847 }
1848 
1849 static void update_links_from_call(struct expression *left,
1850                                    int left_compare,
1851                                    struct expression *right)
1852 {
1853         struct string_list *links;
1854         struct smatch_state *state;
1855         struct compare_data *data;
1856         struct symbol *left_sym, *right_sym;
1857         char *left_var = NULL;
1858         char *right_var = NULL;
1859         struct var_sym_list *left_vsl;
1860         struct expression *expr;
1861         const char *var;
1862         struct var_sym_list *vsl;
1863         int comparison;
1864         char *tmp;
1865 
1866         left_var = chunk_to_var_sym(left, &left_sym);
1867         if (!left_var)
1868                 goto done;
1869         left_vsl = expr_to_vsl(left);
1870         right_var = chunk_to_var_sym(right, &right_sym);
1871         if (!right_var)
1872                 goto done;
1873 
1874         state = get_state(link_id, right_var, right_sym);
1875         if (!state)
1876                 return;
1877         links = state->data;
1878 
1879         FOR_EACH_PTR(links, tmp) {
1880                 state = get_state(compare_id, tmp, NULL);
1881                 if (!state || !state->data)
1882                         continue;
1883                 data = state->data;
1884                 comparison = data->comparison;
1885                 expr = data->right;
1886                 var = data->right_var;
1887                 vsl = data->right_vsl;
1888                 if (strcmp(var, right_var) == 0) {
1889                         expr = data->left;
1890                         var = data->left_var;
1891                         vsl = data->left_vsl;
1892                         comparison = flip_comparison(comparison);
1893                 }
1894                 comparison = combine_comparisons(left_compare, comparison);
1895                 if (!comparison)
1896                         continue;
1897                 add_comparison_var_sym(left, left_var, left_vsl, comparison, expr, var, vsl);
1898         } END_FOR_EACH_PTR(tmp);
1899 
1900 done:
1901         free_string(right_var);
1902 }
1903 
1904 void __add_return_comparison(struct expression *call, const char *range)
1905 {
1906         struct expression *arg;
1907         int comparison;
1908         char buf[4];
1909 
1910         if (!str_to_comparison_arg(range, call, &comparison, &arg))
1911                 return;
1912         snprintf(buf, sizeof(buf), "%s", show_special(comparison));
1913         update_links_from_call(call, comparison, arg);
1914         add_comparison(call, comparison, arg);
1915 }
1916 
1917 void __add_comparison_info(struct expression *expr, struct expression *call, const char *range)
1918 {
1919         copy_comparisons(expr, call);
1920 }
1921 
1922 static char *get_mask_comparison(struct expression *expr, int ignore)
1923 {
1924         struct expression *tmp, *right;
1925         int count, param;
1926         char buf[256];
1927 
1928         /* The return value for "return foo & param;" is <= param */
1929 
1930         count = 0;
1931         while ((tmp = get_assigned_expr(expr))) {
1932                 expr = strip_expr(tmp);
1933                 if (count++ > 4)
1934                         break;
1935         }
1936 
1937         if (expr->type != EXPR_BINOP || expr->op != '&')
1938                 return NULL;
1939 
1940         right = strip_expr(expr->right);
1941         param = get_param_num(right);
1942         if (param < 0 || param == ignore)
1943                 return NULL;
1944 
1945         snprintf(buf, sizeof(buf), "[<=$%d]", param);
1946         return alloc_sname(buf);
1947 }
1948 
1949 static char *range_comparison_to_param_helper(struct expression *expr, char starts_with, int ignore)
1950 {
1951         struct symbol *param;
1952         char *var = NULL;
1953         char buf[256];
1954         char *ret_str = NULL;
1955         int compare;
1956         int i;
1957 
1958         if (!expr)
1959                 return NULL;
1960 
1961         var = chunk_to_var(expr);
1962         if (!var)
1963                 goto try_mask;
1964 
1965         i = -1;
1966         FOR_EACH_PTR(cur_func_sym->ctype.base_type->arguments, param) {
1967                 i++;
1968                 if (i == ignore)
1969                         continue;
1970                 if (!param->ident)
1971                         continue;
1972                 snprintf(buf, sizeof(buf), "%s orig", param->ident->name);
1973                 compare = get_comparison_strings(var, buf);
1974                 if (!compare)
1975                         continue;
1976                 if (show_special(compare)[0] != starts_with)
1977                         continue;
1978                 snprintf(buf, sizeof(buf), "[%s$%d]", show_special(compare), i);
1979                 ret_str = alloc_sname(buf);
1980                 break;
1981         } END_FOR_EACH_PTR(param);
1982 
1983         free_string(var);
1984         if (!ret_str)
1985                 goto try_mask;
1986 
1987         return ret_str;
1988 
1989 try_mask:
1990         if (starts_with == '<')
1991                 ret_str = get_mask_comparison(expr, ignore);
1992         return ret_str;
1993 }
1994 
1995 char *name_sym_to_param_comparison(const char *name, struct symbol *sym)
1996 {
1997         struct symbol *param;
1998         char buf[256];
1999         int compare;
2000         int i;
2001 
2002         i = -1;
2003         FOR_EACH_PTR(cur_func_sym->ctype.base_type->arguments, param) {
2004                 i++;
2005                 if (!param->ident)
2006                         continue;
2007                 snprintf(buf, sizeof(buf), "%s orig", param->ident->name);
2008                 compare = get_comparison_strings(name, buf);
2009                 if (!compare)
2010                         continue;
2011                 snprintf(buf, sizeof(buf), "[%s$%d]", show_special(compare), i);
2012                 return alloc_sname(buf);
2013         } END_FOR_EACH_PTR(param);
2014 
2015         return NULL;
2016 }
2017 
2018 char *expr_equal_to_param(struct expression *expr, int ignore)
2019 {
2020         return range_comparison_to_param_helper(expr, '=', ignore);
2021 }
2022 
2023 char *expr_lte_to_param(struct expression *expr, int ignore)
2024 {
2025         return range_comparison_to_param_helper(expr, '<', ignore);
2026 }
2027 
2028 char *expr_param_comparison(struct expression *expr, int ignore)
2029 {
2030         struct symbol *param;
2031         char *var = NULL;
2032         char buf[256];
2033         char *ret_str = NULL;
2034         int compare;
2035         int i;
2036 
2037         var = chunk_to_var(expr);
2038         if (!var)
2039                 goto free;
2040 
2041         i = -1;
2042         FOR_EACH_PTR(cur_func_sym->ctype.base_type->arguments, param) {
2043                 i++;
2044                 if (i == ignore)
2045                         continue;
2046                 if (!param->ident)
2047                         continue;
2048                 snprintf(buf, sizeof(buf), "%s orig", param->ident->name);
2049                 compare = get_comparison_strings(var, buf);
2050                 if (!compare)
2051                         continue;
2052                 snprintf(buf, sizeof(buf), "[%s$%d]", show_special(compare), i);
2053                 ret_str = alloc_sname(buf);
2054                 break;
2055         } END_FOR_EACH_PTR(param);
2056 
2057 free:
2058         free_string(var);
2059         return ret_str;
2060 }
2061 
2062 char *get_printed_param_name(struct expression *call, const char *param_name, struct symbol *param_sym)
2063 {
2064         struct expression *arg;
2065         char *name;
2066         struct symbol *sym;
2067         static char buf[256];
2068         int len;
2069         int i;
2070 
2071         i = -1;
2072         FOR_EACH_PTR(call->args, arg) {
2073                 i++;
2074 
2075                 name = expr_to_var_sym(arg, &sym);
2076                 if (!name || !sym)
2077                         continue;
2078                 if (sym != param_sym)
2079                         continue;
2080 
2081                 len = strlen(name);
2082                 if (strncmp(name, param_name, len) != 0)
2083                         continue;
2084                 if (param_name[len] == '\0') {
2085                         snprintf(buf, sizeof(buf), "$%d", i);
2086                         return buf;
2087                 }
2088                 if (param_name[len] != '-')
2089                         continue;
2090                 snprintf(buf, sizeof(buf), "$%d%s", i, param_name + len);
2091                 return buf;
2092         } END_FOR_EACH_PTR(arg);
2093 
2094         return NULL;
2095 }
2096 
2097 static void match_call_info(struct expression *expr)
2098 {
2099         struct expression *arg;
2100         struct smatch_state *state;
2101         struct sm_state *sm;
2102         struct compare_data *data;
2103         int comparison;
2104         struct string_list *links;
2105         char *arg_name;
2106         const char *right_name;
2107         char *link;
2108         char info_buf[256];
2109         int i;
2110 
2111         i = -1;
2112         FOR_EACH_PTR(expr->args, arg) {
2113                 i++;
2114 
2115                 state = get_state_chunk(link_id, arg);
2116                 if (!state)
2117                         continue;
2118 
2119                 links = state->data;
2120                 FOR_EACH_PTR(links, link) {
2121                         struct var_sym_list *right_vsl;
2122                         struct var_sym *right_vs;
2123 
2124 
2125                         if (strstr(link, " orig"))
2126                                 continue;
2127                         sm = get_sm_state(compare_id, link, NULL);
2128                         if (!sm)
2129                                 continue;
2130                         data = sm->state->data;
2131                         if (!data || !data->comparison)
2132                                 continue;
2133                         arg_name = expr_to_var(arg);
2134                         if (!arg_name)
2135                                 continue;
2136 
2137                         right_vsl = NULL;
2138                         if (strcmp(data->left_var, arg_name) == 0) {
2139                                 comparison = data->comparison;
2140                                 right_name = data->right_var;
2141                                 right_vsl = data->right_vsl;
2142                         } else if (strcmp(data->right_var, arg_name) == 0) {
2143                                 comparison = flip_comparison(data->comparison);
2144                                 right_name = data->left_var;
2145                                 right_vsl = data->left_vsl;
2146                         }
2147                         if (!right_vsl || ptr_list_size((struct ptr_list *)right_vsl) != 1)
2148                                 goto free;
2149 
2150                         right_vs = first_ptr_list((struct ptr_list *)right_vsl);
2151                         if (strcmp(right_vs->var, right_name) != 0)
2152                                 goto free;
2153                         right_name = get_printed_param_name(expr, right_vs->var, right_vs->sym);
2154                         if (!right_name)
2155                                 goto free;
2156                         snprintf(info_buf, sizeof(info_buf), "%s %s", show_special(comparison), right_name);
2157                         sql_insert_caller_info(expr, PARAM_COMPARE, i, "$", info_buf);
2158 
2159 free:
2160                         free_string(arg_name);
2161                 } END_FOR_EACH_PTR(link);
2162         } END_FOR_EACH_PTR(arg);
2163 }
2164 
2165 static void struct_member_callback(struct expression *call, int param, char *printed_name, struct sm_state *link_sm)
2166 {
2167         struct sm_state *compare_sm;
2168         struct string_list *links;
2169         char *link;
2170         struct compare_data *data;
2171         struct var_sym *left, *right;
2172         static char info_buf[256];
2173         const char *right_name;
2174 
2175         if (strstr(printed_name, " orig"))
2176                 return;
2177 
2178         links = link_sm->state->data;
2179         FOR_EACH_PTR(links, link) {
2180                 compare_sm = get_sm_state(compare_id, link, NULL);
2181                 if (!compare_sm)
2182                         continue;
2183                 data = compare_sm->state->data;
2184                 if (!data || !data->comparison)
2185                         continue;
2186 
2187                 if (ptr_list_size((struct ptr_list *)data->left_vsl) != 1 ||
2188                     ptr_list_size((struct ptr_list *)data->right_vsl) != 1)
2189                         continue;
2190                 left = first_ptr_list((struct ptr_list *)data->left_vsl);
2191                 right = first_ptr_list((struct ptr_list *)data->right_vsl);
2192                 if (left->sym == right->sym &&
2193                     strcmp(left->var, right->var) == 0)
2194                         continue;
2195                 /*
2196                  * Both parameters link to this comparison so only
2197                  * record the first one.
2198                  */
2199                 if (left->sym != link_sm->sym ||
2200                     strcmp(left->var, link_sm->name) != 0)
2201                         continue;
2202 
2203                 right_name = get_printed_param_name(call, right->var, right->sym);
2204                 if (!right_name)
2205                         continue;
2206                 snprintf(info_buf, sizeof(info_buf), "%s %s", show_special(data->comparison), right_name);
2207                 sql_insert_caller_info(call, PARAM_COMPARE, param, printed_name, info_buf);
2208         } END_FOR_EACH_PTR(link);
2209 }
2210 
2211 static void print_return_value_comparison(int return_id, char *return_ranges, struct expression *expr)
2212 {
2213         char *name;
2214         const char *tmp_name;
2215         struct symbol *sym;
2216         int param;
2217         char info_buf[256];
2218 
2219         /*
2220          * TODO: This only prints == comparisons. That's probably the most
2221          * useful comparison because == max has lots of implications.  But it
2222          * would be good to capture the rest as well.
2223          *
2224          * This information is already in the DB but it's in the parameter math
2225          * bits and it's awkward to use it.  This is is the simpler, possibly
2226          * cleaner way, but not necessarily the best, I don't know.
2227          */
2228 
2229         if (!expr)
2230                 return;
2231         name = expr_to_var_sym(expr, &sym);
2232         if (!name || !sym)
2233                 goto free;
2234 
2235         param = get_param_num_from_sym(sym);
2236         if (param < 0)
2237                 goto free;
2238         if (param_was_set_var_sym(name, sym))
2239                 goto free;
2240 
2241         tmp_name = get_param_name_var_sym(name, sym);
2242         if (!tmp_name)
2243                 goto free;
2244 
2245         snprintf(info_buf, sizeof(info_buf), "== $%d%s", param, tmp_name + 1);
2246         sql_insert_return_states(return_id, return_ranges,
2247                                 PARAM_COMPARE, -1, "$", info_buf);
2248 free:
2249         free_string(name);
2250 }
2251 
2252 static void print_return_comparison(int return_id, char *return_ranges, struct expression *expr)
2253 {
2254         struct sm_state *tmp;
2255         struct string_list *links;
2256         char *link;
2257         struct sm_state *sm;
2258         struct compare_data *data;
2259         struct var_sym *left, *right;
2260         int left_param, right_param;
2261         char left_buf[256];
2262         char right_buf[256];
2263         char info_buf[258];
2264         const char *tmp_name;
2265 
2266         print_return_value_comparison(return_id, return_ranges, expr);
2267 
2268         FOR_EACH_MY_SM(link_id, __get_cur_stree(), tmp) {
2269                 if (get_param_num_from_sym(tmp->sym) < 0)
2270                         continue;
2271                 links = tmp->state->data;
2272                 FOR_EACH_PTR(links, link) {
2273                         sm = get_sm_state(compare_id, link, NULL);
2274                         if (!sm)
2275                                 continue;
2276                         data = sm->state->data;
2277                         if (!data || !data->comparison)
2278                                 continue;
2279                         if (ptr_list_size((struct ptr_list *)data->left_vsl) != 1 ||
2280                             ptr_list_size((struct ptr_list *)data->right_vsl) != 1)
2281                                 continue;
2282                         left = first_ptr_list((struct ptr_list *)data->left_vsl);
2283                         right = first_ptr_list((struct ptr_list *)data->right_vsl);
2284                         if (left->sym == right->sym &&
2285                             strcmp(left->var, right->var) == 0)
2286                                 continue;
2287                         /*
2288                          * Both parameters link to this comparison so only
2289                          * record the first one.
2290                          */
2291                         if (left->sym != tmp->sym ||
2292                             strcmp(left->var, tmp->name) != 0)
2293                                 continue;
2294 
2295                         if (strstr(right->var, " orig"))
2296                                 continue;
2297 
2298                         left_param = get_param_num_from_sym(left->sym);
2299                         right_param = get_param_num_from_sym(right->sym);
2300                         if (left_param < 0 || right_param < 0)
2301                                 continue;
2302 
2303                         tmp_name = get_param_name_var_sym(left->var, left->sym);
2304                         if (!tmp_name)
2305                                 continue;
2306                         snprintf(left_buf, sizeof(left_buf), "%s", tmp_name);
2307 
2308                         tmp_name = get_param_name_var_sym(right->var, right->sym);
2309                         if (!tmp_name || tmp_name[0] != '$')
2310                                 continue;
2311                         snprintf(right_buf, sizeof(right_buf), "$%d%s", right_param, tmp_name + 1);
2312 
2313                         /*
2314                          * FIXME: this should reject $ type variables (as
2315                          * opposed to $->foo type).  Those should come from
2316                          * smatch_param_compare_limit.c.
2317                          */
2318 
2319                         snprintf(info_buf, sizeof(info_buf), "%s %s", show_special(data->comparison), right_buf);
2320                         sql_insert_return_states(return_id, return_ranges,
2321                                         PARAM_COMPARE, left_param, left_buf, info_buf);
2322                 } END_FOR_EACH_PTR(link);
2323 
2324         } END_FOR_EACH_SM(tmp);
2325 }
2326 
2327 static int parse_comparison(char **value, int *op)
2328 {
2329 
2330         *op = **value;
2331 
2332         switch (*op) {
2333         case '<':
2334                 (*value)++;
2335                 if (**value == '=') {
2336                         (*value)++;
2337                         *op = SPECIAL_LTE;
2338                 }
2339                 break;
2340         case '=':
2341                 (*value)++;
2342                 (*value)++;
2343                 *op = SPECIAL_EQUAL;
2344                 break;
2345         case '!':
2346                 (*value)++;
2347                 (*value)++;
2348                 *op = SPECIAL_NOTEQUAL;
2349                 break;
2350         case '>':
2351                 (*value)++;
2352                 if (**value == '=') {
2353                         (*value)++;
2354                         *op = SPECIAL_GTE;
2355                 }
2356                 break;
2357         default:
2358                 return 0;
2359         }
2360 
2361         if (**value != ' ') {
2362                 sm_perror("parsing comparison.  %s", *value);
2363                 return 0;
2364         }
2365 
2366         (*value)++;
2367         return 1;
2368 }
2369 
2370 static int split_op_param_key(char *value, int *op, int *param, char **key)
2371 {
2372         static char buf[256];
2373         char *p;
2374 
2375         if (!parse_comparison(&value, op))
2376                 return 0;
2377 
2378         snprintf(buf, sizeof(buf), "%s", value);
2379 
2380         p = buf;
2381         if (*p++ != '$')
2382                 return 0;
2383 
2384         *param = atoi(p);
2385         if (*param < 0 || *param > 99)
2386                 return 0;
2387         p++;
2388         if (*param > 9)
2389                 p++;
2390         p--;
2391         *p = '$';
2392         *key = p;
2393 
2394         return 1;
2395 }
2396 
2397 static void db_return_comparison(struct expression *expr, int left_param, char *key, char *value)
2398 {
2399         struct expression *left_arg, *right_arg;
2400         char *left_name = NULL;
2401         struct symbol *left_sym;
2402         char *right_name = NULL;
2403         struct symbol *right_sym;
2404         int op;
2405         int right_param;
2406         char *right_key;
2407         struct var_sym_list *left_vsl = NULL, *right_vsl = NULL;
2408 
2409         if (left_param == -1) {
2410                 if (expr->type != EXPR_ASSIGNMENT)
2411                         return;
2412                 left_arg = strip_expr(expr->left);
2413 
2414                 while (expr->type == EXPR_ASSIGNMENT)
2415                         expr = strip_expr(expr->right);
2416                 if (expr->type != EXPR_CALL)
2417                         return;
2418         } else {
2419                 while (expr->type == EXPR_ASSIGNMENT)
2420                         expr = strip_expr(expr->right);
2421                 if (expr->type != EXPR_CALL)
2422                         return;
2423 
2424                 left_arg = get_argument_from_call_expr(expr->args, left_param);
2425                 if (!left_arg)
2426                         return;
2427         }
2428 
2429         if (!split_op_param_key(value, &op, &right_param, &right_key))
2430                 return;
2431 
2432         right_arg = get_argument_from_call_expr(expr->args, right_param);
2433         if (!right_arg)
2434                 return;
2435 
2436         left_name = get_variable_from_key(left_arg, key, &left_sym);
2437         if (!left_name || !left_sym)
2438                 goto free;
2439 
2440         right_name = get_variable_from_key(right_arg, right_key, &right_sym);
2441         if (!right_name || !right_sym)
2442                 goto free;
2443 
2444         add_var_sym(&left_vsl, left_name, left_sym);
2445         add_var_sym(&right_vsl, right_name, right_sym);
2446 
2447         add_comparison_var_sym(NULL, left_name, left_vsl, op, NULL, right_name, right_vsl);
2448 
2449 free:
2450         free_string(left_name);
2451         free_string(right_name);
2452 }
2453 
2454 int param_compare_limit_is_impossible(struct expression *expr, int left_param, char *left_key, char *value)
2455 {
2456         struct smatch_state *state;
2457         char *left_name = NULL;
2458         char *right_name = NULL;
2459         struct symbol *left_sym, *right_sym;
2460         struct expression *left_arg, *right_arg;
2461         int op, state_op;
2462         int right_param;
2463         char *right_key;
2464         int ret = 0;
2465         char buf[256];
2466 
2467         while (expr->type == EXPR_ASSIGNMENT)
2468                 expr = strip_expr(expr->right);
2469         if (expr->type != EXPR_CALL)
2470                 return 0;
2471 
2472         if (!split_op_param_key(value, &op, &right_param, &right_key))
2473                 return 0;
2474 
2475         left_arg = get_argument_from_call_expr(expr->args, left_param);
2476         if (!left_arg)
2477                 return 0;
2478 
2479         right_arg = get_argument_from_call_expr(expr->args, right_param);
2480         if (!right_arg)
2481                 return 0;
2482 
2483         left_name = get_variable_from_key(left_arg, left_key, &left_sym);
2484         right_name = get_variable_from_key(right_arg, right_key, &right_sym);
2485         if (!left_name || !right_name)
2486                 goto free;
2487 
2488         snprintf(buf, sizeof(buf), "%s vs %s", left_name, right_name);
2489         state = get_state(compare_id, buf, NULL);
2490         if (!state)
2491                 goto free;
2492         state_op = state_to_comparison(state);
2493         if (!state_op)
2494                 goto free;
2495 
2496         if (!filter_comparison(remove_unsigned_from_comparison(state_op), op))
2497                 ret = 1;
2498 free:
2499         free_string(left_name);
2500         free_string(right_name);
2501         return ret;
2502 }
2503 
2504 int impossibly_high_comparison(struct expression *expr)
2505 {
2506         struct smatch_state *link_state;
2507         struct sm_state *sm;
2508         struct string_list *links;
2509         char *link;
2510         struct compare_data *data;
2511 
2512         link_state = get_state_expr(link_id, expr);
2513         if (!link_state) {
2514                 if (expr->type == EXPR_BINOP &&
2515                     (impossibly_high_comparison(expr->left) ||
2516                      impossibly_high_comparison(expr->right)))
2517                         return 1;
2518                 return 0;
2519         }
2520 
2521         links = link_state->data;
2522         FOR_EACH_PTR(links, link) {
2523                 sm = get_sm_state(compare_id, link, NULL);
2524                 if (!sm)
2525                         continue;
2526                 data = sm->state->data;
2527                 if (!data)
2528                         continue;
2529                 if (!possibly_true(data->left, data->comparison, data->right))
2530                         return 1;
2531         } END_FOR_EACH_PTR(link);
2532 
2533         return 0;
2534 }
2535 
2536 static void free_data(struct symbol *sym)
2537 {
2538         if (__inline_fn)
2539                 return;
2540         clear_compare_data_alloc();
2541 }
2542 
2543 void register_comparison(int id)
2544 {
2545         compare_id = id;
2546         set_dynamic_states(compare_id);
2547         add_hook(&save_start_states, AFTER_DEF_HOOK);
2548         add_unmatched_state_hook(compare_id, unmatched_comparison);
2549         add_pre_merge_hook(compare_id, &pre_merge_hook);
2550         add_merge_hook(compare_id, &merge_compare_states);
2551         add_hook(&free_data, AFTER_FUNC_HOOK);
2552         add_hook(&match_call_info, FUNCTION_CALL_HOOK);
2553         add_split_return_callback(&print_return_comparison);
2554 
2555         select_return_states_hook(PARAM_COMPARE, &db_return_comparison);
2556         add_hook(&match_preop, OP_HOOK);
2557 }
2558 
2559 void register_comparison_late(int id)
2560 {
2561         add_hook(&match_assign, ASSIGNMENT_HOOK);
2562 }
2563 
2564 void register_comparison_links(int id)
2565 {
2566         link_id = id;
2567         db_ignore_states(link_id);
2568         set_dynamic_states(link_id);
2569         add_merge_hook(link_id, &merge_links);
2570         add_modification_hook(link_id, &match_modify);
2571         add_modification_hook_late(link_id, match_inc_dec);
2572 
2573         add_member_info_callback(link_id, struct_member_callback);
2574 }
2575 
2576 void register_comparison_inc_dec(int id)
2577 {
2578         inc_dec_id = id;
2579         add_modification_hook_late(inc_dec_id, &iter_modify);
2580 }
2581 
2582 void register_comparison_inc_dec_links(int id)
2583 {
2584         inc_dec_link_id = id;
2585         set_dynamic_states(inc_dec_link_id);
2586         set_up_link_functions(inc_dec_id, inc_dec_link_id);
2587 }
2588 
2589 static void filter_by_sm(struct sm_state *sm, int op,
2590                        struct state_list **true_stack,
2591                        struct state_list **false_stack)
2592 {
2593         struct compare_data *data;
2594         int istrue = 0;
2595         int isfalse = 0;
2596 
2597         if (!sm)
2598                 return;
2599         data = sm->state->data;
2600         if (!data) {
2601                 if (sm->merged) {
2602                         filter_by_sm(sm->left, op, true_stack, false_stack);
2603                         filter_by_sm(sm->right, op, true_stack, false_stack);
2604                 }
2605                 return;
2606         }
2607 
2608         if (data->comparison &&
2609             data->comparison == filter_comparison(data->comparison, op))
2610                 istrue = 1;
2611 
2612         if (data->comparison &&
2613             data->comparison == filter_comparison(data->comparison, negate_comparison(op)))
2614                 isfalse = 1;
2615 
2616         if (istrue)
2617                 add_ptr_list(true_stack, sm);
2618         if (isfalse)
2619                 add_ptr_list(false_stack, sm);
2620 
2621         if (sm->merged) {
2622                 filter_by_sm(sm->left, op, true_stack, false_stack);
2623                 filter_by_sm(sm->right, op, true_stack, false_stack);
2624         }
2625 }
2626 
2627 struct sm_state *comparison_implication_hook(struct expression *expr,
2628                                 struct state_list **true_stack,
2629                                 struct state_list **false_stack)
2630 {
2631         struct sm_state *sm;
2632         char *left, *right;
2633         int op;
2634         static char buf[256];
2635 
2636         if (expr->type != EXPR_COMPARE)
2637                 return NULL;
2638 
2639         op = expr->op;
2640 
2641         left = expr_to_var(expr->left);
2642         right = expr_to_var(expr->right);
2643         if (!left || !right) {
2644                 free_string(left);
2645                 free_string(right);
2646                 return NULL;
2647         }
2648 
2649         if (strcmp(left, right) > 0) {
2650                 char *tmp = left;
2651 
2652                 left = right;
2653                 right = tmp;
2654                 op = flip_comparison(op);
2655         }
2656 
2657         snprintf(buf, sizeof(buf), "%s vs %s", left, right);
2658         sm = get_sm_state(compare_id, buf, NULL);
2659         if (!sm)
2660                 return NULL;
2661         if (!sm->merged)
2662                 return NULL;
2663 
2664         filter_by_sm(sm, op, true_stack, false_stack);
2665         if (!*true_stack && !*false_stack)
2666                 return NULL;
2667 
2668         if (option_debug)
2669                 sm_msg("implications from comparison: (%s)", show_sm(sm));
2670 
2671         return sm;
2672 }