1 30 31 package jbet; 32 import java.util.*; 33 import java.io.*; 34 35 38 39 public class DataFlow { 40 41 String thisClass; 43 String superClass; 44 45 int maxStack = -1; 47 int maxLocals = -1; 48 Snippit code; 49 Type returnType; 50 51 public int maxStackDetected = -1; 52 public int maxLocalsDetected = -1; 53 54 public LineWriter out = Jbet.debug; 55 56 MethodInfo method; 57 private Instruction current; 58 59 public static String JbetLogFacility = "dataflow"; 60 61 63 public DataFlow(String t, String s, MethodInfo m) { 64 thisClass = t; 65 superClass = s; 66 maxStack = m.maxStack; 67 maxLocals = m.maxLocals; 68 method = m; 69 code = m.code; 70 returnType = m.descriptor.ret; 71 reset(); 72 init(thisClass, m); 73 } 74 75 public DataFlow (MethodInfo mi) { 76 this(mi.cr.thisClass, mi.cr.superClass, mi); 77 } 78 79 80 DataFlow(int maxs, int maxl, Snippit c, Type t, 82 String thisClass, String superClass) { 83 maxStack = maxs; 84 maxLocals = maxl; 85 code = c; 86 returnType = t; 87 this.thisClass = thisClass; 88 this.superClass = superClass; 89 reset(); 90 } 91 92 DataFlow(int maxs, int maxl, Snippit c, Type t) { 93 this(maxs, maxl, c, t, null, null); 94 } 95 96 int stacklimit() { 97 return maxStack == -1 ? 65536 : maxStack; 98 } 99 int locallimit() { 100 return maxLocals == -1 ? 65536 : maxLocals; 101 } 102 103 class Subroutine { 104 Instruction target; 105 BitSet mask; 106 Subroutine(Instruction t, int n) { 107 target = t; 108 mask = new BitSet(n); 109 } 110 Subroutine(Instruction t, BitSet b) { 111 target = t; 112 mask = b; 113 } 114 Subroutine(Subroutine s) { 115 target = s.target; 116 mask = (BitSet) s.mask.clone(); 117 } 118 119 public boolean equals(Object o) { 120 return (o instanceof Subroutine) && 121 target==((Subroutine)o).target; 122 } 123 public String toString() { 124 StringBuffer out = new StringBuffer (); 125 boolean first = true; 126 out.append(target.pc() + "<"); 127 for (int i = 0; i < mask.size(); i++) 128 if (mask.get(i)) { 129 if (first) 130 first = false; 131 else 132 out.append(" "); 133 out.append(i); 134 } 135 out.append(">"); 136 return out.toString(); 137 } 138 } 139 140 141 ProcState makeEmptyProcState() { 142 return new ProcState (); 143 } 144 145 public class ProcState { 146 int stacklen; Type [] stack; 148 Vector[] stacktypes; 149 Type [] locals; 150 Vector[] localtypes; 151 boolean changed; 152 Vector subs; 153 154 Subroutine ret_sub = null; 156 boolean needs_constructor = false; 157 Vector ret_places = null; 159 160 ProcState (int stacksize, int localsize) { 161 stacklen = 0; 162 stack = new Type [ stacksize ]; 163 stacktypes = new Vector [ stacksize ]; 164 locals = new Type [ localsize ]; 165 localtypes = new Vector [ localsize ]; 166 stacklen = 0; 167 changed = true; 168 subs = new Vector(); 169 } 170 171 ProcState () { 172 this( DataFlow.this.maxStack == -1 ? 10 : DataFlow.this.maxStack, 173 DataFlow.this.maxLocals == -1 ? 10 : DataFlow.this.maxLocals ); 174 } 175 176 177 public ProcState (ProcState ps) 178 { 179 stack = new Type [ ps.stack.length ]; 180 stacktypes = new Vector [ ps.stacktypes.length ]; 181 locals = new Type [ ps.locals.length ]; 182 localtypes = new Vector [ ps.localtypes.length ]; 183 184 stacklen = ps.stacklen; 185 186 for (int i = 0; i < stacklen; i++) 187 stack[i] = ps.stack[i]; 188 189 for (int i = 0; i < locals.length; i++) 190 locals[i] = ps.locals[i]; 191 192 for (int i = 0; i < stacktypes.length; i++) 193 if (ps.stacktypes[i] != null) { 194 stacktypes[i] = new Vector(); 195 for (int j = 0; j < ps.stacktypes[i].size(); j++) 196 stacktypes[i].addElement (ps.stacktypes[i].elementAt (j)); 197 } 198 else 199 stacktypes[i] = null; 200 201 for (int i = 0; i < localtypes.length; i++) 202 if (ps.localtypes[i] != null) { 203 localtypes[i] = new Vector(); 204 for (int j = 0; j < ps.localtypes[i].size(); j++) 205 localtypes[i].addElement (ps.localtypes[i].elementAt (j)); 206 } 207 else 208 localtypes[i] = null; 209 210 changed = ps.changed; 211 subs = new Vector( ps.subs.size() ); 212 for (int i = 0; i < ps.subs.size(); i++) 213 subs.addElement( new Subroutine( (Subroutine) ps.subs.elementAt(i) )); 214 needs_constructor = ps.needs_constructor; 215 ret_places = ps.ret_places; 216 } 217 218 ProcState (ProcState ps, ProcState jsr) throws ClassFileException, DataFlowException { 220 this (ps); 221 if (jsr==null) return; 222 reallocLocals (jsr.locals.length); 223 for (int i = 0; i < jsr.locals.length; i++) 224 if (ps.ret_sub.mask.get(i) == false) { 225 la(i); 226 locals[i] = jsr.locals[i]; 227 } 228 } 229 230 231 void reallocLocals(int num) { 232 if ( num < locals.length ) 233 num = locals.length; 234 if (num > locallimit()) 235 num = locallimit(); 236 Type [] newlocals = new Type [ num ]; 237 Vector [] newlocaltypes = new Vector [num]; 238 for (int i = 0; i < locals.length; i++) 239 newlocals[i] = locals[i]; 240 for (int i = 0; i < localtypes.length; i++) 241 newlocaltypes[i] = localtypes[i]; 242 243 locals = newlocals; 244 localtypes = newlocaltypes; 245 } 246 247 void reallocStack() { 248 Type [] newstack = new Type [stack.length + 10]; 249 Vector [] newstacktypes = new Vector [stacktypes.length + 10]; 250 251 for (int i = 0; i < stacklen; i++) { 252 newstack[i] = stack[i]; 253 newstacktypes[i] = stacktypes[i]; 254 } 255 256 stack = newstack; 257 stacktypes = newstacktypes; 258 } 259 260 261 public ProcState dup() { return new ProcState(this); } 262 263 ProcState (ProcState ps, Instruction instr) throws ClassFileException, DataFlowException { 264 this(ps); 265 model(instr); 266 } 267 268 ProcState (Descriptor d, boolean virtual, boolean init, String thisClass) { 269 this(DataFlow.this.maxStack == -1 ? 10 : DataFlow.this.maxStack, 270 DataFlow.this.maxLocals == -1 ? d.count() : DataFlow.this.maxLocals); 271 int start; 272 if (virtual) { 273 if (locals.length < 1) 274 locals = new Type[1]; 275 if (init) { 276 locals[0] = new Type('l', 0, thisClass, null); 277 needs_constructor = true; 278 } else 279 locals[0] = new Type('L', 0, thisClass); 280 start = 1; 281 } else 282 start = 0; 283 284 int j = start; 285 for (int i = 0; i < d.args.length; i++) { 286 locals[j++] = d.args[i].compType(); 287 288 if (d.args[i].category()==2) 289 locals[j++] = Type.DASH; 290 } 291 } 292 293 int lastLocal() { 294 int i; 295 for (i = locals.length; --i >= 0 && locals[i] == null;); 296 return i; 297 } 298 299 public void printout () { 300 if (needs_constructor) 301 out.println("needs_constructor"); 302 out.print("stack: "); 303 for (int i = 0; i < stacklen; i++) 304 out.print(" " + (stack[i]==null ? "?" : stack[i].toString())); 305 out.println(); 306 307 out.print("locals:"); 308 int last = lastLocal(); 309 for (int i = 0; i <= last; i++) 310 out.print(" " + i + ":" +(locals[i]==null ? "?" : locals[i].toString())); 311 out.println(); 312 313 331 332 if (subs.size() != 0) { 333 out.print("subs: "); 334 for (int i = 0; i < subs.size(); i++) { 335 Subroutine sub = (Subroutine) subs.elementAt(i); 336 out.print(" " + sub); 337 } 338 out.println(); 339 } 340 } 341 342 346 private void sa(int depth, Type type) throws ClassFileException, DataFlowException { 347 if (depth > stacklen) 348 throw new DataFlowException (method, current, "pop off empty stack"); 349 if (type == null) return; 350 if ( stack[stacklen-depth] == null ) throw new DataFlowException 351 (method, current, "attempt to use a defunct value on the stack"); 352 if (! stack[stacklen-depth].isa(type)) 353 throw new DataFlowException (method, current, "type mismatch on stack"); 354 if ( (type.equals(Type.DOUBLE) || type.equals(Type.LONG)) && 355 ( depth==1 || !stack[(stacklen-depth)+1].equals(Type.DASH)) ) 356 throw new DataFlowException (method, current, "second half of double or long is bad"); 357 } 358 359 363 private void sa(int depth, int category) throws ClassFileException, DataFlowException { 364 sa(depth); 365 if (st(depth).category() != category) 366 throw new DataFlowException (method, current, "element on stack is wrong category"); 367 if (category == 2 &&( depth==stacklen-1 || !st(depth+1).equals(Type.DASH))) 368 throw new DataFlowException (method, current, "incomplete category 2 type"); 369 } 370 371 375 private void sa_uc(int depth, String cname) throws ClassFileException, DataFlowException { 376 if (depth > stacklen) 377 throw new DataFlowException (method, current, "pop off empty stack"); 378 if ( stack[stacklen-depth] == null ) throw new DataFlowException 379 (method, current, "attempt to use a defunct value on the stack"); 380 381 Type se = stack[stacklen-depth]; 382 if (se.base == 'l' && se.cname.equals (cname) && 383 method.classrep().toString().equals (cname)) 384 return; 385 if (! se.isa(Type.class2type(cname))) 386 throw new DataFlowException (method, current, "type mismatch on stack"); 387 } 388 389 private void sa(int num) throws ClassFileException, DataFlowException { sa(num, null); } 390 private void la(int num) throws ClassFileException, DataFlowException { la(num, null); } 391 392 private void sa(Descriptor d) throws ClassFileException, DataFlowException { 393 int j = 0; 394 for (int i = 1; i <= d.args.length; i++) { 395 Type t = d.args[d.args.length - i].compType(); 396 j += t.category(); 397 sa(j, t); 398 } 399 } 400 401 402 private void la(int num, Type type) throws ClassFileException, DataFlowException { 403 if (num >= locallimit() || num < 0) 404 throw new DataFlowException(method, current, "local index out of range"); 405 if (type == null) 406 { 407 if (num >= locals.length) 408 reallocLocals(num+10); 409 return; 410 } 411 412 if (num >= locals.length || (type.category()==2 && num+1>=locals.length)) 413 reallocLocals(num+10); 414 if (locals[num] == null) throw new UninitializedLocalException(method, current, num, type); 415 if (!locals[num].isa(type)) 416 throw new DataFlowException (method, current, "type mismatch for local variable (" + locals[num] + " should be " + type + ")"); 417 if ( (type.equals(Type.DOUBLE) || type.equals(Type.LONG)) && 418 (num==locals.length-1 || locals[num+1]==null || 419 !locals[num+1].equals(Type.DASH))) 420 throw new DataFlowException 421 (method, current, "second half of double or long is bad"); 422 } 423 424 private void checkpush (int n) throws DataFlowException { 425 426 if (stacklen + n > stacklimit()) 427 throw new DataFlowException (method, current, "stack overflow"); 428 if (stacklen + n > stack.length) 429 reallocStack(); 430 } 431 432 void push (Type t) throws DataFlowException 433 { 434 checkpush (t.category()); 435 stacktypes[stacklen] = null; 436 stack[stacklen++] = t; 437 if (t.category() == 2) { 438 stacktypes[stacklen] = null; 439 stack[stacklen++] = Type.DASH; 440 } 441 } 442 443 public Type st(int i) { 444 return stack[stacklen -i]; 445 } 446 447 448 public Vector stt (int i) 449 { 450 if (stacktypes[ stacklen - i] != null) 451 return stacktypes [stacklen - i]; 452 else { 453 Vector v = new Vector(); 454 v.addElement (stack [stacklen - i]); 455 return v; 456 } 457 } 458 459 Vector new_stt (int i) 460 { 461 if (stacktypes[ stacklen - i] != null) 462 return (Vector) (stacktypes [stacklen - i].clone()); 463 else { 464 Vector v = new Vector(); 465 v.addElement (stack [stacklen - i]); 466 return v; 467 } 468 } 469 470 Vector localt (int i) 471 { 472 if (localtypes [i] != null) 473 return localtypes [i]; 474 else { 475 Vector v = new Vector(); 476 v.addElement (locals [i]); 477 return v; 478 } 479 } 480 481 Vector new_localt (int i) 482 { 483 if (localtypes [i] != null) 484 return (Vector) (localtypes [i].clone()); 485 else { 486 Vector v = new Vector(); 487 v.addElement (locals [i]); 488 return v; 489 } 490 } 491 492 Vector copy_localt (int i) 493 { 494 return localtypes[i] == null ? null : (Vector)(localtypes[i].clone()); 495 } 496 497 Vector copy_stt (int i) 498 { 499 return stacktypes[i] == null ? null : (Vector)(stacktypes[i].clone()); 500 } 501 502 void clearUninitialized (Instruction target) { 503 for (int i = 0; i < stacklen; i++) 504 if ( stack[i] != null && 505 stack[i].base=='l' && stack[i].target()==target ) 506 stack[i] = null; 507 for (int i = 0; i < locals.length; i++) 508 if ( locals[i] != null && 509 locals[i].base=='l' && locals[i].target()==target ) 510 locals[i] = null; 511 } 512 513 514 void clearAllUninitialized () { 515 for (int i = 0; i < stacklen; i++) 516 if ( stack[i]!=null && stack[i].base=='l') 517 stack[i] = null; 518 for (int i = 0; i < locals.length; i++) 519 if ( locals[i]!=null && locals[i].base=='l') 520 locals[i] = null; 521 } 522 523 524 void initialize(Instruction target) { 525 for (int i = 0; i < stacklen; i++) 526 if ( stack[i]!=null && 527 stack[i].base=='l' && stack[i].target()==target ) { 528 stack[i] = Type.class2type( stack[i].cname ); 529 stacktypes[i] = null; 530 } 531 for (int i = 0; i < locals.length; i++) { 532 if ( locals[i]!=null && 533 locals[i].base=='l' && locals[i].target()==target ) { 534 locals[i] = Type.class2type( locals[i].cname ); 535 localtypes[i] = null; 536 } 537 } 538 } 539 540 void setBits(int lvt) { 541 for (int i = 0; i < subs.size(); i++) 542 ((Subroutine)subs.elementAt(i)).mask.set(lvt); 543 } 544 545 546 void modelMethod(Descriptor d, boolean virtual) throws DataFlowException { 547 stacklen -= d.count() - (virtual ? 0 : 1); 548 if (d.ret.base == 'V') return; 549 checkpush(d.ret.category()); 550 stacktypes[stacklen] = null; 551 stack[stacklen++] = d.ret.compType(); 552 if (d.ret.category() == 2) 553 stack[stacklen++] = Type.DASH; 554 } 555 556 void checkret(Type t) throws ClassFileException, DataFlowException { 557 if (returnType==null) throw new DataFlowException 558 (method, current, "not allowed to return"); 559 if (! t.isa(returnType.compType())) throw new DataFlowException 560 (method, current, "wrong return type " + t + " should be " + returnType.compType()); 561 } 562 563 void model(Instruction instr) throws ClassFileException, DataFlowException { 564 565 current = instr; 566 567 ret_sub = null; 568 ret_places = null; 569 570 Type t; 571 Vector ty; 572 Descriptor d; 573 String str; 574 575 switch(instr.opCode()) { 576 case Instruction.OP_AALOAD: 577 sa(1, Type.INT); 578 sa(2, Type.REFARRAY); 579 t = st(2).popbracket(); 580 stacktypes[stacklen-2] = new_stt(2); 581 582 stacklen -= 2; 583 584 if (stacktypes[stacklen] != null) { 585 stacktypes[stacklen] = copy_stt (stacklen); 586 587 for (int j = 0; j < stacktypes[stacklen].size(); j++) 588 ((Type) stacktypes[stacklen].elementAt (j)).popbracket(); 589 } 590 591 stack[stacklen++] = t; 592 break; 593 594 case Instruction.OP_AASTORE: 595 sa(2, Type.INT); 596 sa(3, Type.REFARRAY); 597 sa(1, st(3).popbracket()); 598 stacklen -= 3; 599 break; 600 601 case Instruction.OP_BASTORE: 602 sa(1, Type.INT); 603 sa(2, Type.INT); 604 sa(3); 605 if (!st(3).isa(Type.BOOLARRAY) && !st(3).isa(Type.BYTEARRAY)) 606 throw new DataFlowException(method, current, "type mismatch on stack"); 607 stacklen -= 3; 608 break; 609 610 case Instruction.OP_CASTORE: 611 sa(1, Type.INT); 612 sa(2, Type.INT); 613 sa(3, Type.CHARARRAY); 614 stacklen -= 3; 615 break; 616 617 case Instruction.OP_ACONST_NULL: 618 checkpush (1); 619 stacktypes[stacklen] = null; 620 stack[stacklen++] = Type.NULL; 621 break; 622 623 case Instruction.OP_ALOAD: 624 la (instr.lvtIndex()); 625 t = locals[instr.lvtIndex()]; 626 627 if (t==null || !(t.isa(Type.RETADDR) || t.isUninitialized())) 628 la(instr.lvtIndex(), Type.OBJECT); 629 630 633 634 checkpush (1); 635 stacktypes[stacklen] = copy_localt (instr.lvtIndex()); 636 stack[stacklen++] = locals[instr.lvtIndex()]; 637 setBits(instr.lvtIndex()); 638 break; 639 640 case Instruction.OP_ANEWARRAY: 641 sa(1, Type.INT); 642 t = Type.class2type(instr.classRef()); 643 t.arraydepth++; 644 stacktypes[stacklen - 1] = null; 645 stack[stacklen - 1] = t; 646 break; 647 648 case Instruction.OP_MULTIANEWARRAY: 649 for (int i = 0; i < instr.immediate(); i++) { 650 sa(1, Type.INT); 651 stacklen--; 652 } 653 t = Type.class2type(instr.classRef()); 654 stacktypes[stacklen] = null; 655 stack[stacklen++] = t; 656 break; 657 658 case Instruction.OP_ARETURN: 659 sa(1, Type.OBJECT); 660 checkret(st(1)); 661 if (needs_constructor) throw new DataFlowException 662 (method, current, "return from a constructor without this() or super()"); 663 break; 664 665 case Instruction.OP_DRETURN: 666 checkret(Type.DOUBLE); 667 if (needs_constructor) throw new DataFlowException 668 (method, current, "return from a constructor without this() or super()"); 669 sa(2, Type.DOUBLE); 670 break; 671 672 case Instruction.OP_FRETURN: 673 checkret(Type.FLOAT); 674 if (needs_constructor) throw new DataFlowException 675 (method, current, "return from a constructor without this() or super()"); 676 sa(1, Type.FLOAT); 677 break; 678 679 case Instruction.OP_GOTO: 680 case Instruction.OP_GOTO_W: 681 break; 682 683 case Instruction.OP_ATHROW: 684 sa(1, Type.THROWABLE); 685 stacklen--; 686 break; 687 688 case Instruction.OP_ARRAYLENGTH: 689 sa(1); 690 691 if (!st(1).isa(Type.ARRAY)) 692 throw new DataFlowException(method, current, "arraylength expects an array type"); 693 stacktypes[stacklen - 1] = null; 694 stack[stacklen - 1] = Type.INT; 695 break; 696 697 case Instruction.OP_ASTORE: 698 sa(1); 699 700 if (st(1)==null || !(st(1).isa(Type.RETADDR) || st(1).isUninitialized())) 701 sa(1, Type.OBJECT); 702 703 708 709 la(instr.lvtIndex()); 710 setBits(instr.lvtIndex()); 711 locals[ instr.lvtIndex() ] = stack[--stacklen]; 712 localtypes [instr.lvtIndex()] = copy_stt (stacklen); 713 break; 714 715 case Instruction.OP_BALOAD: 716 sa(1, Type.INT); 717 sa(2); 718 if (!st(2).isa(Type.BOOLARRAY) && !st(2).isa(Type.BYTEARRAY)) 719 throw new DataFlowException(method, current, "type mismatch on stack"); 720 stacklen -= 2; 721 stack[stacklen++] = Type.INT; 722 break; 723 724 case Instruction.OP_CALOAD: 725 sa(1, Type.INT); 726 sa(2); 727 if (!st(2).isa(Type.CHARARRAY)) 728 throw new DataFlowException(method, current, "type mismatch on stack"); 729 stacklen -= 2; 730 stack[stacklen++] = Type.INT; 731 break; 732 733 case Instruction.OP_BIPUSH: 734 checkpush (1); 735 stack[ stacklen++ ] = Type.INT; 736 break; 737 738 case Instruction.OP_CHECKCAST: 739 sa(1, Type.OBJECT); 740 stacktypes[stacklen-1] = null; 741 stack[stacklen-1] = Type.class2type(instr.classRef()); 742 break; 743 744 case Instruction.OP_D2F: 745 sa(2, Type.DOUBLE); 746 stack[--stacklen - 1] = Type.FLOAT; 747 break; 748 749 case Instruction.OP_D2I: 750 sa(2, Type.DOUBLE); 751 stack[--stacklen - 1] = Type.INT; 752 break; 753 754 case Instruction.OP_D2L: 755 sa(2, Type.DOUBLE); 756 stack[stacklen - 2] = Type.LONG; 757 break; 758 759 case Instruction.OP_DALOAD: 760 sa(1, Type.INT); 761 sa(2, Type.DOUBLEARRAY); 762 stack[stacklen - 2] = Type.DOUBLE; 763 stack[stacklen - 1] = Type.DASH; 764 break; 765 766 case Instruction.OP_DASTORE: 767 sa(2, Type.DOUBLE); 768 sa(3, Type.INT); 769 sa(4, Type.DOUBLEARRAY); 770 stacklen -= 4; 771 break; 772 773 case Instruction.OP_DCMPG: 774 case Instruction.OP_DCMPL: 775 sa(2, Type.DOUBLE); 776 sa(4, Type.DOUBLE); 777 stacklen -= 4; 778 stack[stacklen++] = Type.INT; 779 break; 780 781 case Instruction.OP_DDIV: 782 case Instruction.OP_DMUL: 783 case Instruction.OP_DREM: 784 case Instruction.OP_DSUB: 785 case Instruction.OP_DADD: 786 sa(2, Type.DOUBLE); 787 sa(4, Type.DOUBLE); 788 stacklen -= 2; 789 break; 790 791 case Instruction.OP_DLOAD: 792 la (instr.lvtIndex(), Type.DOUBLE); 793 checkpush (2); 794 stack[stacklen++] = Type.DOUBLE; 795 stack[stacklen++] = Type.DASH; 796 setBits(instr.lvtIndex()); 797 setBits(instr.lvtIndex() + 1); 798 break; 799 800 case Instruction.OP_DNEG: 801 sa(2, Type.DOUBLE); 802 break; 803 804 case Instruction.OP_DSTORE: 805 sa(2, Type.DOUBLE); 806 la (instr.lvtIndex()); 807 la (instr.lvtIndex() + 1); 808 stacklen -= 2; 809 810 localtypes[instr.lvtIndex() ] = null; 811 localtypes[instr.lvtIndex() + 1] = null; 812 813 locals[instr.lvtIndex() ] = Type.DOUBLE; 814 locals[instr.lvtIndex() + 1] = Type.DASH; 815 setBits(instr.lvtIndex()); 816 setBits(instr.lvtIndex() + 1); 817 break; 818 819 case Instruction.OP_DUP: 820 checkpush (1); 821 sa(1); 822 if (st(1).equals(Type.DASH)) 823 throw new DataFlowException(method, current, "can't dup a double"); 824 stacktypes[stacklen] = copy_stt (stacklen-1); 825 stack[stacklen] = stack[stacklen-1]; 826 stacklen++; 827 break; 828 829 case Instruction.OP_DUP2: 830 checkpush (2); 831 sa(2); 832 if (st(2).equals(Type.DASH)) 833 throw new DataFlowException(method, current, "dup2 would break up a category 2 type"); 834 835 stacktypes[stacklen ] = copy_stt (stacklen-2); 836 stacktypes[stacklen+1] = copy_stt (stacklen-1); 837 838 stack[stacklen] = stack[stacklen-2]; 839 stack[stacklen+1] = stack[stacklen-1]; 840 841 stacklen += 2; 842 break; 843 844 case Instruction.OP_DUP2_X1: 845 sa(3, 1); 846 if ( !(st(2).category()==2 && st(1).equals(Type.DASH)) && 847 !(st(1).category()==1 && st(1).category()==1) ) 848 throw new DataFlowException(method, current, "bad stack for dup2_x1"); 849 checkpush (2); 850 851 stack[stacklen+1] = stack[stacklen-1]; 852 stack[stacklen] = stack[stacklen-2]; 853 stack[stacklen-1] = stack[stacklen-3]; 854 stack[stacklen-2] = stack[stacklen+1]; 855 stack[stacklen-3] = stack[stacklen]; 856 857 stacktypes[stacklen+1] = copy_stt (stacklen-1); 858 stacktypes[stacklen] = copy_stt (stacklen-2); 859 stacktypes[stacklen-1] = copy_stt (stacklen-3); 860 stacktypes[stacklen-2] = copy_stt (stacklen+1); 861 stacktypes[stacklen-3] = copy_stt (stacklen ); 862 863 stacklen += 2; 864 break; 865 866 case Instruction.OP_DUP2_X2: 867 sa(4); 868 if ( !(st(1).category()==1 && st(2).category()==1 && 869 st(3).category()==1 && st(4).category()==1 ) && 870 !(st(1).equals(Type.DASH) && st(2).category()==2 && 871 st(3).category()==1 && st(4).category()==1 ) && 872 !(st(1).category()==1 && st(2).category()==1 && 873 st(3).equals(Type.DASH) && st(4).category()==2 ) && 874 !(st(1).equals(Type.DASH) && st(2).category()==2 && 875 st(3).equals(Type.DASH) && st(4).category()==2 ) ) 876 throw new DataFlowException(method, current, "bad stack for dup2_x2"); 877 checkpush (2); 878 879 stack[stacklen+1] = stack[stacklen-1]; 880 stack[stacklen] = stack[stacklen-2]; 881 stack[stacklen-1] = stack[stacklen-3]; 882 stack[stacklen-2] = stack[stacklen-4]; 883 stack[stacklen-3] = stack[stacklen+1]; 884 stack[stacklen-4] = stack[stacklen]; 885 886 stacktypes[stacklen+1] = copy_stt (stacklen-1); 887 stacktypes[stacklen] = copy_stt (stacklen-2); 888 stacktypes[stacklen-1] = copy_stt (stacklen-3); 889 stacktypes[stacklen-2] = copy_stt (stacklen-4); 890 stacktypes[stacklen-3] = copy_stt (stacklen+1); 891 stacktypes[stacklen-4] = copy_stt (stacklen ); 892 893 stacklen += 2; 894 break; 895 896 case Instruction.OP_DUP_X1: 897 sa(1, 1); 898 sa(2, 1); 899 checkpush (1); 900 stack[stacklen] = stack[stacklen-1]; 901 stack[stacklen-1] = stack[stacklen-2]; 902 stack[stacklen-2] = stack[stacklen]; 903 904 stacktypes[stacklen] = copy_stt (stacklen-1); 905 stacktypes[stacklen-1] = copy_stt (stacklen-2); 906 stacktypes[stacklen-2] = copy_stt (stacklen ); 907 908 stacklen++; 909 break; 910 911 case Instruction.OP_DUP_X2: 912 sa(3); 913 sa(1, 1); 914 if ( !(st(2).category()==1 && st(3).category()==1) && 915 !(st(3).category()==2 && st(2).equals(Type.DASH)) ) 916 throw new DataFlowException(method, current, "bad stack for dup_x2"); 917 checkpush (1); 918 919 stack[stacklen] = stack[stacklen-1]; 920 stack[stacklen-1] = stack[stacklen-2]; 921 stack[stacklen-2] = stack[stacklen-3]; 922 stack[stacklen-3] = stack[stacklen]; 923 924 stacktypes[stacklen] = copy_stt (stacklen-1); 925 stacktypes[stacklen-1] = copy_stt (stacklen-2); 926 stacktypes[stacklen-2] = copy_stt (stacklen-3); 927 stacktypes[stacklen-3] = copy_stt (stacklen ); 928 929 stacklen++; 930 break; 931 932 case Instruction.OP_F2D: 933 sa(1, Type.FLOAT); 934 checkpush (1); 935 936 stack[stacklen-1] = Type.DOUBLE; 937 stack[stacklen] = Type.DASH; 938 stacklen++; 939 break; 940 941 case Instruction.OP_F2I: 942 sa(1, Type.FLOAT); 943 stack[stacklen-1] = Type.INT; 944 break; 945 946 case Instruction.OP_F2L: 947 sa(1, Type.FLOAT); 948 checkpush (1); 949 stack[stacklen-1] = Type.LONG; 950 stack[stacklen] = Type.DASH; 951 stacklen++; 952 break; 953 954 case Instruction.OP_FADD: 955 case Instruction.OP_FDIV: 956 case Instruction.OP_FMUL: 957 case Instruction.OP_FREM: 958 case Instruction.OP_FSUB: 959 sa(1, Type.FLOAT); 960 sa(2, Type.FLOAT); 961 stacklen--; 962 break; 963 964 case Instruction.OP_FNEG: 965 sa(1, Type.FLOAT); 966 break; 967 968 case Instruction.OP_FALOAD: 969 sa(1, Type.INT); 970 sa(2, Type.FLOATARRAY); 971 stacklen -= 2; 972 stack[stacklen++] = Type.FLOAT; 973 break; 974 975 case Instruction.OP_FASTORE: 976 sa(1, Type.FLOAT); 977 sa(2, Type.INT); 978 sa(3, Type.FLOATARRAY); 979 stacklen -= 3; 980 break; 981 982 case Instruction.OP_FCMPG: 983 case Instruction.OP_FCMPL: 984 sa(1, Type.FLOAT); 985 sa(2, Type.FLOAT); 986 stacklen -= 2; 987 stack[stacklen++] = Type.INT; 988 break; 989 990 case Instruction.OP_FLOAD: 991 la (instr.lvtIndex(), Type.FLOAT); 992 checkpush (1); 993 stack[stacklen++] = Type.FLOAT; 994 setBits(instr.lvtIndex()); 995 break; 996 997 case Instruction.OP_FSTORE: 998 la (instr.lvtIndex()); 999 sa (1, Type.FLOAT); 1000 locals[ instr.lvtIndex() ] = stack[--stacklen]; 1001 localtypes[instr.lvtIndex()] = null; 1002 setBits(instr.lvtIndex()); 1003 break; 1004 1005 case Instruction.OP_GETFIELD: 1006 sa_uc(1, instr.classRef()); 1007 t = instr.type().compType(); 1008 checkpush (t.category() - 1); 1009 stack[stacklen-1] = t; 1010 stacktypes[stacklen-1] = null; 1011 if ( t.category() == 2 ) { 1012 stacktypes[stacklen] = null; 1013 stack[stacklen++] = Type.DASH; 1014 } 1015 break; 1016 1017 case Instruction.OP_GETSTATIC: 1018 t = instr.type().compType(); 1019 checkpush (t.category()); 1020 stacktypes[stacklen] = null; 1021 stack[stacklen++] = t; 1022 if ( t.category() == 2 ) { 1023 stacktypes[stacklen] = null; 1024 stack[stacklen++] = Type.DASH; 1025 } 1026 break; 1027 1028 case Instruction.OP_I2D: 1029 sa(1, Type.INT); 1030 checkpush (1); 1031 stack[stacklen - 1] = Type.DOUBLE; 1032 stack[stacklen++ ] = Type.DASH; 1033 break; 1034 1035 case Instruction.OP_I2L: 1036 sa(1, Type.INT); 1037 checkpush (1); 1038 stack[stacklen - 1] = Type.LONG; 1039 stack[stacklen++ ] = Type.DASH; 1040 break; 1041 1042 case Instruction.OP_I2F: 1043 sa(1, Type.INT); 1044 stack[stacklen - 1] = Type.FLOAT; 1045 break; 1046 1047 case Instruction.OP_I2B: 1048 case Instruction.OP_I2C: 1049 case Instruction.OP_I2S: 1050 case Instruction.OP_INEG: 1051 sa(1, Type.INT); 1052 break; 1053 1054 1055 case Instruction.OP_IALOAD: 1056 sa(1, Type.INT); 1057 sa(2, Type.INTARRAY); 1058 stacklen -= 2; 1059 stack[stacklen++] = Type.INT; 1060 break; 1061 1062 case Instruction.OP_IASTORE: 1063 sa(1, Type.INT); 1064 sa(2, Type.INT); 1065 sa(3, Type.INTARRAY); 1066 stacklen -= 3; 1067 break; 1068 1069 1070 case Instruction.OP_IF_ACMPEQ: 1071 case Instruction.OP_IF_ACMPNE: 1072 sa(1, Type.OBJECT); 1073 sa(2, Type.OBJECT); 1074 stacklen -= 2; 1075 break; 1076 1078 case Instruction.OP_IF_ICMPEQ: 1079 case Instruction.OP_IF_ICMPGE: 1080 case Instruction.OP_IF_ICMPGT: 1081 case Instruction.OP_IF_ICMPLE: 1082 case Instruction.OP_IF_ICMPLT: 1083 case Instruction.OP_IF_ICMPNE: 1084 sa(1, Type.INT); 1085 sa(2, Type.INT); 1086 stacklen -= 2; 1087 break; 1088 1090 1091 case Instruction.OP_IFEQ: 1092 case Instruction.OP_IFGE: 1093 case Instruction.OP_IFGT: 1094 case Instruction.OP_IFLE: 1095 case Instruction.OP_IFLT: 1096 case Instruction.OP_IFNE: 1097 sa(1, Type.INT); 1098 stacklen -= 1; 1099 break; 1100 1102 case Instruction.OP_IFNONNULL: 1103 case Instruction.OP_IFNULL: 1104 sa(1, Type.OBJECT); 1105 stacklen--; 1106 break; 1107 1108 case Instruction.OP_IINC: 1109 la (instr.lvtIndex(), Type.INT); 1110 localtypes[instr.lvtIndex()] = null; 1111 locals[instr.lvtIndex()] = Type.INT; 1112 setBits( instr.lvtIndex() ); 1113 break; 1114 1115 case Instruction.OP_ILOAD: 1116 la (instr.lvtIndex(), Type.INT); 1117 checkpush (1); 1118 stack[stacklen++] = Type.INT; 1119 setBits( instr.lvtIndex() ); 1120 break; 1121 1122 case Instruction.AOP_IPUSH: 1123 checkpush (1); 1124 stack[stacklen++] = Type.INT; 1125 break; 1126 1127 case Instruction.AOP_FPUSH: 1128 checkpush (1); 1129 stack[stacklen++] = Type.FLOAT; 1130 break; 1131 1132 case Instruction.AOP_LPUSH: 1133 checkpush (2); 1134 stack[stacklen++] = Type.LONG; 1135 stack[stacklen++] = Type.DASH; 1136 break; 1137 1138 case Instruction.AOP_SPUSH: 1139 checkpush (1); 1140 stacktypes[stacklen] = null; 1141 stack[stacklen++] = Type.STRING; 1142 break; 1143 1144 case Instruction.AOP_DPUSH: 1145 checkpush (2); 1146 stack[stacklen++] = Type.DOUBLE; 1147 stack[stacklen++] = Type.DASH; 1148 break; 1149 1150 case Instruction.OP_INSTANCEOF: 1151 sa(1, Type.OBJECT); 1152 stack[ stacklen - 1] = Type.INT; 1153 break; 1154 1155 1156 case Instruction.OP_INVOKESPECIAL: 1157 if (instr.elemName().equals("<init>")) { 1158 d = instr.descriptor(); 1159 int count = d.count(); 1160 sa(d); 1161 sa(count); 1162 Type instanceptr = st(count); 1163 if (instanceptr == null) throw new DataFlowException 1164 (method, current, "initializer call on a bogus value"); 1165 if (instanceptr.arraydepth != 0) throw new DataFlowException 1166 (method, current, "call to <init> on an array"); 1167 if (instanceptr.base != 'l') throw new DataFlowException 1168 (method, current, "call to <init> on an initialized object or primitive type"); 1169 if (instanceptr.target() == null) { 1170 1171 if (!instr.classRef().equals(thisClass) && 1172 !instr.classRef().equals(superClass)) throw new 1173 DataFlowException(method, current, "call to wrong initializer"); 1174 initialize(null); 1175 needs_constructor = false; 1176 modelMethod(d, true); 1177 } else { 1178 if (! instr.classRef().equals(instanceptr.cname)) throw new 1179 DataFlowException(method, current, "call to wrong initializer"); 1180 initialize(instanceptr.target()); 1181 modelMethod(d, true); 1182 } 1183 break; 1184 } else 1185 ; 1187 case Instruction.OP_INVOKEVIRTUAL: 1188 case Instruction.OP_INVOKEINTERFACE: 1189 d = instr.descriptor(); 1190 sa(d); 1191 sa(d.count(), Type.class2type(instr.classRef()) ); 1192 modelMethod(d, true); 1193 break; 1194 1195 1196 1197 case Instruction.OP_INVOKESTATIC: 1198 d = instr.descriptor(); 1199 sa(d); 1200 modelMethod(d, false); 1201 break; 1202 1203 case Instruction.OP_IRETURN: 1204 checkret(Type.INT); 1205 if (needs_constructor) throw new DataFlowException 1206 (method, current, "return from a constructor without this() or super()"); 1207 sa(1, Type.INT); 1208 break; 1209 1210 case Instruction.OP_ISTORE: 1211 sa (1, Type.INT); 1212 la(instr.lvtIndex()); 1213 locals[ instr.lvtIndex() ] = stack[--stacklen]; 1214 localtypes [instr.lvtIndex()] = null; 1215 setBits(instr.lvtIndex()); 1216 break; 1217 1218 case Instruction.OP_IOR: 1219 case Instruction.OP_IREM: 1220 case Instruction.OP_ISHL: 1221 case Instruction.OP_IMUL: 1222 case Instruction.OP_IAND: 1223 case Instruction.OP_IADD: 1224 case Instruction.OP_ISHR: 1225 case Instruction.OP_ISUB: 1226 case Instruction.OP_IUSHR: 1227 case Instruction.OP_IDIV: 1228 case Instruction.OP_IXOR: 1229 sa (1, Type.INT); 1230 sa (2, Type.INT); 1231 stacklen--; 1232 break; 1233 1234 case Instruction.OP_JSR: 1235 case Instruction.OP_JSR_W: 1236 checkpush (1); 1237 clearAllUninitialized(); 1238 stack[stacklen++] = new Type('R', 0, null, instr.branchTarget().instr); 1239 subs.addElement(new Subroutine(instr.branchTarget().instr, 1240 locals.length)); 1241 break; 1242 1243 case Instruction.OP_L2D: 1244 sa(2, Type.LONG); 1245 stacklen -= 2; 1246 stack[stacklen++] = Type.DOUBLE; 1247 stack[stacklen++] = Type.DASH; 1248 break; 1249 1250 case Instruction.OP_L2F: 1251 sa(2, Type.LONG); 1252 stacklen -= 2; 1253 stack[stacklen++] = Type.FLOAT; 1254 break; 1255 1256 case Instruction.OP_L2I: 1257 sa(2, Type.LONG); 1258 stacklen -= 2; 1259 stack[stacklen++] = Type.INT; 1260 break; 1261 1262 case Instruction.OP_LALOAD: 1263 sa(1, Type.INT); 1264 sa(2, Type.LONGARRAY); 1265 stack[stacklen - 2] = Type.LONG; 1266 stack[stacklen - 1] = Type.DASH; 1267 break; 1268 1269 case Instruction.OP_LASTORE: 1270 sa(2, Type.LONG); 1271 sa(3, Type.INT); 1272 sa(4, Type.LONGARRAY); 1273 stacklen -= 4; 1274 break; 1275 1276 case Instruction.OP_LCMP: 1277 sa(2, Type.LONG); 1278 sa(4, Type.LONG); 1279 stacklen -= 4; 1280 stack[stacklen++] = Type.INT; 1281 break; 1282 1283 case Instruction.OP_LLOAD: 1284 la (instr.lvtIndex(), Type.LONG); 1285 checkpush (2); 1286 stack[stacklen++] = Type.LONG; 1287 stack[stacklen++] = Type.DASH; 1288 setBits( instr.lvtIndex() ); 1289 setBits( instr.lvtIndex() + 1 ); 1290 break; 1291 1292 case Instruction.OP_LADD: 1293 case Instruction.OP_LAND: 1294 case Instruction.OP_LDIV: 1295 case Instruction.OP_LMUL: 1296 case Instruction.OP_LOR: 1297 case Instruction.OP_LREM: 1298 case Instruction.OP_LSUB: 1299 case Instruction.OP_LXOR: 1300 sa(2, Type.LONG); 1301 sa(4, Type.LONG); 1302 stacklen -= 2; 1303 break; 1304 1305 case Instruction.OP_LSHL: 1306 case Instruction.OP_LSHR: 1307 case Instruction.OP_LUSHR: 1308 sa(1, Type.INT); 1309 sa(3, Type.LONG); 1310 stacklen -= 1; 1311 break; 1312 1313 case Instruction.OP_LNEG: 1314 sa(2, Type.LONG); 1315 break; 1316 1317 case Instruction.OP_LOOKUPSWITCH: 1318 sa(1, Type.INT); 1319 stacklen--; 1320 break; 1321 1322 case Instruction.OP_LRETURN: 1323 checkret(Type.LONG); 1324 if (needs_constructor) throw new DataFlowException 1325 (method, current, "return from a constructor without this() or super()"); 1326 sa(2, Type.LONG); 1327 break; 1328 1329 case Instruction.OP_LSTORE: 1330 la (instr.lvtIndex()); 1331 la (instr.lvtIndex()+1); 1332 sa (2, Type.LONG); 1333 1334 stacklen -= 2; 1335 locals[ instr.lvtIndex() ] = Type.LONG; 1336 locals[ instr.lvtIndex()+1] = Type.DASH; 1337 setBits(instr.lvtIndex()); 1338 setBits(instr.lvtIndex() + 1); 1339 break; 1340 1341 1342 case Instruction.OP_MONITORENTER: 1343 case Instruction.OP_MONITOREXIT: 1344 sa(1, Type.OBJECT); 1345 stacklen--; 1346 break; 1347 1348 case Instruction.OP_NEW: 1349 clearUninitialized(instr); 1350 t = new Type('l', 0, instr.classRef(), instr); 1351 checkpush (1); 1352 1353 stacktypes[stacklen] = null; 1354 stack[stacklen++] = t; 1355 break; 1356 1357 case Instruction.OP_NEWARRAY: 1358 sa(1, Type.INT); 1359 stacktypes[stacklen - 1] = null; 1360 1361 switch (instr.immediate ()) { 1362 case Instruction.NAT_BOOLEAN: 1363 stack[ stacklen - 1] = Type.BOOLARRAY; break; 1364 case Instruction.NAT_FLOAT: 1365 stack[ stacklen - 1] = Type.FLOATARRAY; break; 1366 case Instruction.NAT_DOUBLE: 1367 stack[ stacklen - 1] = Type.DOUBLEARRAY; break; 1368 case Instruction.NAT_BYTE: 1369 stack[ stacklen - 1] = Type.BYTEARRAY; break; 1370 case Instruction.NAT_SHORT: 1371 stack[ stacklen - 1] = Type.SHORTARRAY; break; 1372 case Instruction.NAT_INT: 1373 stack[ stacklen - 1] = Type.INTARRAY; break; 1374 case Instruction.NAT_LONG: 1375 stack[ stacklen - 1] = Type.LONGARRAY; break; 1376 case Instruction.NAT_CHAR: 1377 stack[ stacklen - 1] = Type.CHARARRAY; break; 1378 } 1379 break; 1380 1381 case Instruction.OP_NOP: 1382 break; 1383 1384 case Instruction.OP_POP: 1385 sa(1, 1); 1386 stacklen --; 1387 break; 1388 1389 case Instruction.OP_POP2: 1390 if (stacklen < 2) throw new DataFlowException 1391 (method, current, "pop off empty stack"); 1392 if (st(2).equals(Type.DASH)) throw new DataFlowException 1393 (method, current, "pop2 would break up a catagory 2 type"); 1394 stacklen -= 2; 1395 break; 1396 1397 case Instruction.OP_PUTFIELD: 1398 sa_uc( 1 + instr.type().category(), instr.classRef()); 1399 sa( instr.type().category(), instr.type().compType() ); 1400 stacklen -= 1 + instr.type().category(); 1401 break; 1402 1403 case Instruction.OP_PUTSTATIC: 1404 sa( instr.type().category(), instr.type().compType() ); 1405 stacklen -= instr.type().category(); 1406 break; 1407 1408 case Instruction.OP_RET: { 1409 la (instr.lvtIndex(), Type.RETADDR); 1410 if ( locals[instr.lvtIndex()].extra == null ) 1411 throw new DataFlowException 1412 (method, current, "attempt to share a ret between 2 jsr targets"); 1413 clearAllUninitialized(); 1414 setBits( instr.lvtIndex() ); 1415 t = locals[ instr.lvtIndex() ]; 1416 Subroutine sub; 1417 while (true) { 1418 if (subs.size() == 0) 1419 throw new DataFlowException(method, current, "bad return from subroutine"); 1420 sub = (Subroutine) subs.lastElement(); 1421 subs.removeElementAt( subs.size()-1 ); 1422 if ( sub.target == t.target() ) break; 1423 } 1424 ret_sub = sub; 1425 break; 1426 } 1427 1428 case Instruction.OP_RETURN: 1429 checkret(Type.VOID); 1430 if (needs_constructor) throw new DataFlowException 1431 (method, current, "return from a constructor without this() or super()"); 1432 break; 1433 1434 case Instruction.OP_SALOAD: 1435 sa(1, Type.INT); 1436 sa(2, Type.SHORTARRAY); 1437 stacklen -= 2; 1438 stack[ stacklen++ ] = Type.INT; 1439 break; 1440 1441 case Instruction.OP_SASTORE: 1442 sa(1, Type.INT); 1443 sa(2, Type.INT); 1444 sa(3, Type.SHORTARRAY); 1445 stacklen -= 3; 1446 break; 1447 1448 case Instruction.OP_SIPUSH: 1449 checkpush (1); 1450 stack[ stacklen++ ] = Type.INT; 1451 break; 1452 1453 case Instruction.OP_SWAP: 1454 sa(1, 1); 1455 sa(2, 1); 1456 1457 t = stack[ stacklen - 1]; 1458 ty = copy_stt (stacklen - 1); 1459 1460 stack[ stacklen - 1] = stack[ stacklen - 2]; 1461 stack[ stacklen - 2] = t; 1462 1463 stacktypes [stacklen - 1] = copy_stt (stacklen - 2); 1464 stacktypes [stacklen - 2] = ty; 1465 break; 1466 1467 case Instruction.OP_TABLESWITCH: 1468 sa(1, Type.INT); 1469 stacklen--; 1470 break; 1471 1472 case Instruction.AOP_COMMENT: 1473 case Instruction.AOP_EXCMARKER: 1474 break; 1475 1476 default: 1477 { 1478 int op = instr.opCode(); 1479 throw new DataFlowException(method, current, "bad opcode " + op); 1480 } 1481 1482 } 1483 } 1484 1485 void model (Snippit s) throws ClassFileException, DataFlowException { 1486 for (Instruction instr = s.head; instr != null; instr = instr.next) { 1487 model (instr); 1488 } 1489 } 1490 1491 void exception(String type) throws DataFlowException { 1492 stacklen = 0; 1493 checkpush(1); 1494 stack[stacklen++] = Type.class2type(type); 1495 } 1496 1497 1502 1503 void mergeInto (ProcState ps, ProcState after_jsr, String exception) throws ClassFileException, DataFlowException { 1504 1505 1508 1509 if (locals.length < ps.locals.length) 1510 for (int i = locals.length; i < ps.locals.length; i++) 1511 ps.locals[i] = null; 1512 int numlocals = locals.length < ps.locals.length ? locals.length : 1513 ps.locals.length; 1514 1515 for (int i = 0; i < numlocals; i++) { 1516 if (ps.locals[i] == null) continue; 1517 Type t = ps.locals[i].merge 1518 ( ret_sub==null || ret_sub.mask.get(i) ? 1519 locals[i] : after_jsr.locals[i] ); 1520 if (t==null || !t.equals( ps.locals[i] )) { 1521 ps.changed = true; 1522 1523 1524 Type orig = ps.locals[i]; 1525 Type newt = ret_sub==null || ret_sub.mask.get(i) ? locals[i] : after_jsr.locals[i]; 1526 boolean addorig = (orig.base == 'L'); 1527 boolean addnewt = (newt != null && newt.base == 'L'); 1528 1529 if (ps.localtypes[i] != null) 1530 for (int j = 0; j < ps.localtypes[i].size(); j++) { 1531 if (addorig && orig.equals (ps.localtypes[i].elementAt (j))) 1532 addorig = false; 1533 if (addnewt && newt.equals (ps.localtypes[i].elementAt (j))) 1534 addnewt = false; 1535 } 1536 else 1537 ps.localtypes[i] = new Vector(); 1538 1539 if (addorig) 1540 ps.localtypes[i].addElement (orig); 1541 if (addnewt) 1542 ps.localtypes[i].addElement (newt); 1543 1544 ps.locals[i] = t; 1545 } 1546 } 1547 1548 if (exception == null) { 1549 if (stacklen != ps.stacklen) 1550 throw new DataFlowException 1551 (method, current, "stack lengths do not match (merging into " + ps + ")"); 1552 1553 for (int i = 0; i < stacklen; i++) { 1554 Type t = ps.stack[i].merge( stack[i] ); 1555 if (t == null) 1556 throw new DataFlowException (method, current, "unknown type on stack"); 1557 if (!t.equals( ps.stack[i] )) { 1558 ps.changed = true; 1559 1560 Type orig = ps.stack[i]; 1561 Type newt = stack[i]; 1562 boolean addorig = (orig.base == 'L'); 1563 boolean addnewt = (newt != null && newt.base == 'L'); 1564 1565 if (ps.stacktypes[i] != null) 1566 for (int j = 0; j < ps.stacktypes[i].size(); j++) { 1567 if (orig.equals (ps.stacktypes[i].elementAt (j))) 1568 addorig = false; 1569 if (newt.equals (ps.stacktypes[i].elementAt (j))) 1570 addnewt = false; 1571 } 1572 else 1573 ps.stacktypes[i] = new Vector(); 1574 1575 if (addorig) 1576 ps.stacktypes[i].addElement (orig); 1577 if (addnewt) 1578 ps.stacktypes[i].addElement (newt); 1579 1580 ps.stack[i] = t; 1581 } 1582 } 1583 } else { 1584 if (ps.stacklen != 1) throw new DataFlowException 1585 (method, current, "non-1 stack length at start of exception handler: " + ps.stacklen); 1586 Type t = Type.class2type(exception); 1587 t = Type.merge(t, ps.stack[0]); 1588 if (t == null) 1589 throw new DataFlowException (method, current, "unknown type on stack"); 1590 if (!t.equals( ps.stack[0] )) { 1591 ps.changed = true; 1592 1593 Type orig = ps.stack[0]; 1594 Type newt = stack[0]; 1595 boolean addorig = (orig.base == 'L'); 1596 boolean addnewt = (newt != null && newt.base == 'L'); 1597 1598 if (ps.stacktypes[0] != null) 1599 for (int j = 0; j < ps.stacktypes[0].size(); j++) { 1600 if (orig.equals (ps.stacktypes[0].elementAt (j))) 1601 addorig = false; 1602 if (newt.equals (ps.stacktypes[0].elementAt (j))) 1603 addnewt = false; 1604 } 1605 else 1606 ps.stacktypes[0] = new Vector(); 1607 1608 if (addorig) 1609 ps.stacktypes[0].addElement (orig); 1610 if (addnewt) 1611 ps.stacktypes[0].addElement (newt); 1612 1613 ps.stack[0] = t; 1614 } 1615 } 1616 1617 if (needs_constructor != ps.needs_constructor) throw new 1618 DataFlowException (method, current, "cannot tell if constructor has been called"); 1619 1620 for (int i = 0; i < ps.subs.size();) { 1621 Subroutine is = (Subroutine) ps.subs.elementAt(i); 1622 int j = subs.indexOf( is ); 1623 if ( j != -1 ) { 1624 Subroutine js = (Subroutine) subs.elementAt(j); 1625 if (! is.mask.equals(js.mask)) { 1626 is.mask.or(js.mask); 1627 ps.changed = true; 1628 } 1629 i++; 1630 } else { 1631 ps.subs.removeElementAt(i); 1632 ps.changed = true; 1633 } 1634 } 1635 1636 } 1637 } 1638 1639 void reset() { 1640 for (Instruction instr = code.first(); instr != null; 1641 instr = instr.next) 1642 instr.setProcState(null); 1643 } 1644 1645 void init(String thisClass, MethodInfo mi) { 1646 code.first().setProcState( new ProcState(mi.descriptor, !mi.isStatic(), 1648 mi.name.equals("<init>"), 1649 thisClass)); 1650 } 1651 1652 public void run () throws DataFlowException, ClassFileException { 1653 run (false); 1654 } 1655 1656 public void run (boolean only_one_round) throws DataFlowException, ClassFileException { 1657 Vector successors = new Vector(); 1658 Instruction first = code.first(); 1659 1660 boolean done = false; 1661 1662 while (!done) { 1663 out.println("=================ROUND============"); 1664 1665 done = true; 1666 for (Instruction instr = first; instr != null; instr = instr.next) 1667 if (instr.procState() != null && instr.procState().changed) { 1668 done = false; 1669 instr.procState().changed = false; 1670 current = instr; 1671 1672 out.println("INSTRUCTION " + 1673 instr.pc() + " " + instr.recString()); 1674 instr.procState().printout(); 1675 1676 1678 for (int i = 0; i < code.numEx(); i++) { 1679 ExceptionRec ex = code.exAt(i); 1680 String catchType = ex.catchType == null ? 1681 "java/lang/Throwable" : ex.catchType; 1682 Instruction ei = ex.start.instr; 1683 Instruction handler = ex.handler.instr; 1684 do { 1685 if (ei == instr) { 1686 if (handler.procState() == null) { 1687 ProcState ps = new ProcState(instr.procState()); 1688 ps.exception(catchType); 1689 ps.changed = true; 1690 handler.setProcState(ps); 1691 } else { 1692 instr.procState().mergeInto 1693 (handler.procState(), null, catchType); 1694 } 1695 } 1696 if ( ei == ex.end.instr) break; 1697 ei = ei.next; 1698 } while ( true ); 1699 } 1700 1701 1703 ProcState ps = new ProcState(instr.procState()); 1704 ps.model(instr); 1705 1706 out.println("------------"); 1707 ps.printout(); 1708 out.print("\n\n\n"); 1709 1710 1712 successors.removeAllElements(); 1713 1714 if (instr.usesBranch()) 1715 successors.addElement (instr.branchTarget().instr); 1716 1717 if (instr.opCode () != Instruction.OP_GOTO && 1718 instr.opCode () != Instruction.OP_GOTO_W && 1719 instr.opCode () != Instruction.OP_JSR && 1720 instr.opCode () != Instruction.OP_RET && 1721 instr.opCode () != Instruction.OP_ATHROW && 1722 !instr.isReturn () && instr.next != null) 1723 successors.addElement (instr.next); 1724 1725 1726 if (instr.isSwitch ()) { 1727 BranchTarget[] swa = instr.switchArray(); 1728 1729 for (int i = 0; i < swa.length; i++) 1730 successors.addElement (swa[i].instr); 1731 } 1732 1733 boolean isret = instr.opCode() == Instruction.OP_RET; 1734 1735 if (isret) { 1736 ProcState ips = instr.procState(); 1737 if (ips.ret_places == null) { 1738 ips.ret_places = new Vector(); 1739 for (Instruction j = first; j != null; j = j.next) 1740 if (j.opCode() == Instruction.OP_JSR && 1741 j.branchTarget().instr == ps.ret_sub.target) 1742 ips.ret_places.addElement(j.next); 1743 } 1744 for (int j = 0; j < ips.ret_places.size(); j++) { 1745 Instruction k = 1746 (Instruction) ips.ret_places.elementAt(j); 1747 if (k.prev.procState() != null) 1748 successors.addElement(k); 1749 else 1750 instr.procState().changed = true; 1755 } 1756 } 1757 1758 1771 1772 for (int i = 0; i < successors.size(); i++) { 1774 Instruction succ = (Instruction) successors.elementAt(i); 1775 if ( succ.procState() == null ) { 1776 succ.setProcState 1777 (new ProcState (ps, 1778 isret ? succ.prev.procState() : null)); 1779 succ.procState().changed = true; 1780 } else { 1781 ps.mergeInto(succ.procState(), 1782 (isret ? succ.prev.procState() : null), 1783 null); 1784 } 1785 } 1786 1787 } if (only_one_round) 1789 break; } 1792 1793 out.println("=================DONE============"); 1794 for (Instruction instr = first; instr != null; instr = instr.next) { 1795 out.println("INSTRUCTION " + instr.pc() + " " + instr.recString()); 1796 if (instr.procState() != null) { 1797 instr.procState().printout(); 1798 1799 if (instr.procState().stacklen > maxStackDetected) 1800 maxStackDetected = instr.procState().stacklen; 1801 if (instr.procState().lastLocal()+1 > maxLocalsDetected) 1802 maxLocalsDetected = instr.procState().lastLocal()+1; 1803 } 1804 1805 out.println(); 1806 1807 } 1808 1809 1810 } } 1812 1813 1814 1815 | Popular Tags |