1 package com.sun.org.apache.bcel.internal.verifier.statics; 2 3 56 57 import com.sun.org.apache.bcel.internal.*; 58 import com.sun.org.apache.bcel.internal.generic.*; 59 import com.sun.org.apache.bcel.internal.classfile.*; 60 import com.sun.org.apache.bcel.internal.verifier.*; 61 import com.sun.org.apache.bcel.internal.verifier.exc.*; 62 import java.util.ArrayList ; 63 import java.util.HashMap ; 64 65 76 public final class Pass3aVerifier extends PassVerifier{ 77 78 79 private Verifier myOwner; 80 81 86 private int method_no; 87 88 89 InstructionList instructionList; 90 91 Code code; 92 93 94 public Pass3aVerifier(Verifier owner, int method_no){ 95 myOwner = owner; 96 this.method_no = method_no; 97 } 98 99 116 public VerificationResult do_verify(){ 117 if (myOwner.doPass2().equals(VerificationResult.VR_OK)){ 118 JavaClass jc = Repository.lookupClass(myOwner.getClassName()); 121 Method[] methods = jc.getMethods(); 122 if (method_no >= methods.length){ 123 throw new InvalidMethodException("METHOD DOES NOT EXIST!"); 124 } 125 Method method = methods[method_no]; 126 code = method.getCode(); 127 128 if ( method.isAbstract() || method.isNative() ){ return VerificationResult.VR_OK; 131 } 132 133 try{ 143 instructionList = new InstructionList(method.getCode().getCode()); 144 } 145 catch(RuntimeException re){ 146 return new VerificationResult(VerificationResult.VERIFIED_REJECTED, "Bad bytecode in the code array of the Code attribute of method '"+method+"'."); 147 } 148 149 instructionList.setPositions(true); 150 151 VerificationResult vr = VerificationResult.VR_OK; try{ 154 delayedPass2Checks(); 155 } 156 catch(ClassConstraintException cce){ 157 vr = new VerificationResult(VerificationResult.VERIFIED_REJECTED, cce.getMessage()); 158 return vr; 159 } 160 try{ 161 pass3StaticInstructionChecks(); 162 pass3StaticInstructionOperandsChecks(); 163 } 164 catch(StaticCodeConstraintException scce){ 165 vr = new VerificationResult(VerificationResult.VERIFIED_REJECTED, scce.getMessage()); 166 } 167 return vr; 168 } 169 else{ return VerificationResult.VR_NOTYET; 171 } 172 } 173 174 183 private void delayedPass2Checks(){ 184 185 int[] instructionPositions = instructionList.getInstructionPositions(); 186 int codeLength = code.getCode().length; 187 188 LineNumberTable lnt = code.getLineNumberTable(); 192 if (lnt != null){ 193 LineNumber[] lineNumbers = lnt.getLineNumberTable(); 194 IntList offsets = new IntList(); 195 lineNumber_loop: for (int i=0; i < lineNumbers.length; i++){ for (int j=0; j < instructionPositions.length; j++){ 197 int offset = lineNumbers[i].getStartPC(); 199 if (instructionPositions[j] == offset){ 200 if (offsets.contains(offset)){ 201 addMessage("LineNumberTable attribute '"+code.getLineNumberTable()+"' refers to the same code offset ('"+offset+"') more than once which is violating the semantics [but is sometimes produced by IBM's 'jikes' compiler]."); 202 } 203 else{ 204 offsets.add(offset); 205 } 206 continue lineNumber_loop; 207 } 208 } 209 throw new ClassConstraintException("Code attribute '"+code+"' has a LineNumberTable attribute '"+code.getLineNumberTable()+"' referring to a code offset ('"+lineNumbers[i].getStartPC()+"') that does not exist."); 210 } 211 } 212 213 218 Attribute[] atts = code.getAttributes(); 219 for (int a=0; a<atts.length; a++){ 220 if (atts[a] instanceof LocalVariableTable){ 221 LocalVariableTable lvt = (LocalVariableTable) atts[a]; 222 if (lvt != null){ 223 LocalVariable[] localVariables = lvt.getLocalVariableTable(); 224 for (int i=0; i<localVariables.length; i++){ 225 int startpc = localVariables[i].getStartPC(); 226 int length = localVariables[i].getLength(); 227 228 if (!contains(instructionPositions, startpc)){ 229 throw new ClassConstraintException("Code attribute '"+code+"' has a LocalVariableTable attribute '"+code.getLocalVariableTable()+"' referring to a code offset ('"+startpc+"') that does not exist."); 230 } 231 if ( (!contains(instructionPositions, startpc+length)) && (startpc+length != codeLength) ){ 232 throw new ClassConstraintException("Code attribute '"+code+"' has a LocalVariableTable attribute '"+code.getLocalVariableTable()+"' referring to a code offset start_pc+length ('"+(startpc+length)+"') that does not exist."); 233 } 234 } 235 } 236 } 237 } 238 239 CodeException[] exceptionTable = code.getExceptionTable(); 246 for (int i=0; i<exceptionTable.length; i++){ 247 int startpc = exceptionTable[i].getStartPC(); 248 int endpc = exceptionTable[i].getEndPC(); 249 int handlerpc = exceptionTable[i].getHandlerPC(); 250 if (startpc >= endpc){ 251 throw new ClassConstraintException("Code attribute '"+code+"' has an exception_table entry '"+exceptionTable[i]+"' that has its start_pc ('"+startpc+"') not smaller than its end_pc ('"+endpc+"')."); 252 } 253 if (!contains(instructionPositions, startpc)){ 254 throw new ClassConstraintException("Code attribute '"+code+"' has an exception_table entry '"+exceptionTable[i]+"' that has a non-existant bytecode offset as its start_pc ('"+startpc+"')."); 255 } 256 if ( (!contains(instructionPositions, endpc)) && (endpc != codeLength)){ 257 throw new ClassConstraintException("Code attribute '"+code+"' has an exception_table entry '"+exceptionTable[i]+"' that has a non-existant bytecode offset as its end_pc ('"+startpc+"') [that is also not equal to code_length ('"+codeLength+"')]."); 258 } 259 if (!contains(instructionPositions, handlerpc)){ 260 throw new ClassConstraintException("Code attribute '"+code+"' has an exception_table entry '"+exceptionTable[i]+"' that has a non-existant bytecode offset as its handler_pc ('"+handlerpc+"')."); 261 } 262 } 263 } 264 265 272 private void pass3StaticInstructionChecks(){ 273 274 279 if (! (code.getCode().length < 65536)){ throw new StaticCodeInstructionConstraintException("Code array in code attribute '"+code+"' too big: must be smaller than 65536 bytes."); 281 } 282 283 285 288 290 295 InstructionHandle ih = instructionList.getStart(); 299 while (ih != null){ 300 Instruction i = ih.getInstruction(); 301 if (i instanceof IMPDEP1){ 302 throw new StaticCodeInstructionConstraintException("IMPDEP1 must not be in the code, it is an illegal instruction for _internal_ JVM use!"); 303 } 304 if (i instanceof IMPDEP2){ 305 throw new StaticCodeInstructionConstraintException("IMPDEP2 must not be in the code, it is an illegal instruction for _internal_ JVM use!"); 306 } 307 if (i instanceof BREAKPOINT){ 308 throw new StaticCodeInstructionConstraintException("BREAKPOINT must not be in the code, it is an illegal instruction for _internal_ JVM use!"); 309 } 310 ih = ih.getNext(); 311 } 312 313 Instruction last = instructionList.getEnd().getInstruction(); 318 if (! ((last instanceof ReturnInstruction) || 319 (last instanceof RET) || 320 (last instanceof GotoInstruction) || 321 (last instanceof ATHROW) )) throw new StaticCodeInstructionConstraintException("Execution must not fall off the bottom of the code array. This constraint is enforced statically as some existing verifiers do - so it may be a false alarm if the last instruction is not reachable."); 323 } 324 325 334 private void pass3StaticInstructionOperandsChecks(){ 335 344 346 ConstantPoolGen cpg = new ConstantPoolGen(Repository.lookupClass(myOwner.getClassName()).getConstantPool()); 347 InstOperandConstraintVisitor v = new InstOperandConstraintVisitor(cpg); 348 349 InstructionHandle ih = instructionList.getStart(); 351 while (ih != null){ 352 Instruction i = ih.getInstruction(); 353 354 if (i instanceof JsrInstruction){ 356 InstructionHandle target = ((JsrInstruction) i).getTarget(); 357 if (target == instructionList.getStart()){ 358 throw new StaticCodeInstructionOperandConstraintException("Due to JustIce's clear definition of subroutines, no JSR or JSR_W may have a top-level instruction (such as the very first instruction, which is targeted by instruction '"+ih+"' as its target."); 359 } 360 if (!(target.getInstruction() instanceof ASTORE)){ 361 throw new StaticCodeInstructionOperandConstraintException("Due to JustIce's clear definition of subroutines, no JSR or JSR_W may target anything else than an ASTORE instruction. Instruction '"+ih+"' targets '"+target+"'."); 362 } 363 } 364 365 ih.accept(v); 367 368 ih = ih.getNext(); 369 } 370 371 } 372 373 374 private static boolean contains(int[] ints, int i){ 375 for (int j=0; j<ints.length; j++){ 376 if (ints[j]==i) return true; 377 } 378 return false; 379 } 380 381 382 public int getMethodNo(){ 383 return method_no; 384 } 385 386 390 private class InstOperandConstraintVisitor extends com.sun.org.apache.bcel.internal.generic.EmptyVisitor{ 391 392 private ConstantPoolGen cpg; 393 394 395 InstOperandConstraintVisitor(ConstantPoolGen cpg){ 396 this.cpg = cpg; 397 } 398 399 403 private int max_locals(){ 404 return Repository.lookupClass(myOwner.getClassName()).getMethods()[method_no].getCode().getMaxLocals(); 405 } 406 407 410 private void constraintViolated(Instruction i, String message) { 411 throw new StaticCodeInstructionOperandConstraintException("Instruction "+i+" constraint violated: "+message); 412 } 413 414 418 private void indexValid(Instruction i, int idx){ 419 if (idx < 0 || idx >= cpg.getSize()){ 420 constraintViolated(i, "Illegal constant pool index '"+idx+"'."); 421 } 422 } 423 424 431 public void visitLoadClass(LoadClass o){ 432 ObjectType t = o.getLoadClassType(cpg); 433 if (t != null){ Verifier v = VerifierFactory.getVerifier(t.getClassName()); 435 VerificationResult vr = v.doPass1(); 436 if (vr.getStatus() != VerificationResult.VERIFIED_OK){ 437 constraintViolated((Instruction) o, "Class '"+o.getLoadClassType(cpg).getClassName()+"' is referenced, but cannot be loaded: '"+vr+"'."); 438 } 439 } 440 } 441 442 445 447 449 450 public void visitLDC(LDC o){ 452 indexValid(o, o.getIndex()); 453 Constant c = cpg.getConstant(o.getIndex()); 454 if (! ( (c instanceof ConstantInteger) || 455 (c instanceof ConstantFloat) || 456 (c instanceof ConstantString) ) ){ 457 constraintViolated(o, "Operand of LDC or LDC_W must be one of CONSTANT_Integer, CONSTANT_Float or CONSTANT_String, but is '"+c+"'."); 458 } 459 } 460 461 462 public void visitLDC2_W(LDC2_W o){ 464 indexValid(o, o.getIndex()); 465 Constant c = cpg.getConstant(o.getIndex()); 466 if (! ( (c instanceof ConstantLong) || 467 (c instanceof ConstantDouble) ) ){ 468 constraintViolated(o, "Operand of LDC2_W must be CONSTANT_Long or CONSTANT_Double, but is '"+c+"'."); 469 } 470 try{ 471 indexValid(o, o.getIndex()+1); 472 } 473 catch(StaticCodeInstructionOperandConstraintException e){ 474 throw new AssertionViolatedException("OOPS: Does not BCEL handle that? LDC2_W operand has a problem."); 475 } 476 } 477 478 479 public void visitFieldInstruction(FieldInstruction o){ 481 indexValid(o, o.getIndex()); 482 Constant c = cpg.getConstant(o.getIndex()); 483 if (! (c instanceof ConstantFieldref)){ 484 constraintViolated(o, "Indexing a constant that's not a CONSTANT_Fieldref but a '"+c+"'."); 485 } 486 } 487 488 489 public void visitInvokeInstruction(InvokeInstruction o){ 490 indexValid(o, o.getIndex()); 491 if ( (o instanceof INVOKEVIRTUAL) || 492 (o instanceof INVOKESPECIAL) || 493 (o instanceof INVOKESTATIC) ){ 494 Constant c = cpg.getConstant(o.getIndex()); 495 if (! (c instanceof ConstantMethodref)){ 496 constraintViolated(o, "Indexing a constant that's not a CONSTANT_Methodref but a '"+c+"'."); 497 } 498 else{ 499 ConstantNameAndType cnat = (ConstantNameAndType) (cpg.getConstant(((ConstantMethodref) c).getNameAndTypeIndex())); 501 ConstantUtf8 cutf8 = (ConstantUtf8) (cpg.getConstant(cnat.getNameIndex())); 502 if (cutf8.getBytes().equals(Constants.CONSTRUCTOR_NAME) && (!(o instanceof INVOKESPECIAL)) ){ 503 constraintViolated(o, "Only INVOKESPECIAL is allowed to invoke instance initialization methods."); 504 } 505 if ( (! (cutf8.getBytes().equals(Constants.CONSTRUCTOR_NAME)) ) && (cutf8.getBytes().startsWith("<")) ){ 506 constraintViolated(o, "No method with a name beginning with '<' other than the instance initialization methods may be called by the method invocation instructions."); 507 } 508 } 509 } 510 else{ Constant c = cpg.getConstant(o.getIndex()); 512 if (! (c instanceof ConstantInterfaceMethodref)){ 513 constraintViolated(o, "Indexing a constant that's not a CONSTANT_InterfaceMethodref but a '"+c+"'."); 514 } 515 520 ConstantNameAndType cnat = (ConstantNameAndType) (cpg.getConstant(((ConstantInterfaceMethodref)c).getNameAndTypeIndex())); 522 String name = ((ConstantUtf8) (cpg.getConstant(cnat.getNameIndex()))).getBytes(); 523 if (name.equals(Constants.CONSTRUCTOR_NAME)){ 524 constraintViolated(o, "Method to invoke must not be '"+Constants.CONSTRUCTOR_NAME+"'."); 525 } 526 if (name.equals(Constants.STATIC_INITIALIZER_NAME)){ 527 constraintViolated(o, "Method to invoke must not be '"+Constants.STATIC_INITIALIZER_NAME+"'."); 528 } 529 } 530 531 533 Type t = o.getReturnType(cpg); 534 if (t instanceof ArrayType){ 535 t = ((ArrayType) t).getBasicType(); 536 } 537 if (t instanceof ObjectType){ 538 Verifier v = VerifierFactory.getVerifier(((ObjectType) t).getClassName()); 539 VerificationResult vr = v.doPass2(); 540 if (vr.getStatus() != VerificationResult.VERIFIED_OK){ 541 constraintViolated(o, "Return type class/interface could not be verified successfully: '"+vr.getMessage()+"'."); 542 } 543 } 544 545 Type[] ts = o.getArgumentTypes(cpg); 546 for (int i=0; i<ts.length; i++){ 547 t = ts[i]; 548 if (t instanceof ArrayType){ 549 t = ((ArrayType) t).getBasicType(); 550 } 551 if (t instanceof ObjectType){ 552 Verifier v = VerifierFactory.getVerifier(((ObjectType) t).getClassName()); 553 VerificationResult vr = v.doPass2(); 554 if (vr.getStatus() != VerificationResult.VERIFIED_OK){ 555 constraintViolated(o, "Argument type class/interface could not be verified successfully: '"+vr.getMessage()+"'."); 556 } 557 } 558 } 559 560 } 561 562 563 public void visitINSTANCEOF(INSTANCEOF o){ 564 indexValid(o, o.getIndex()); 565 Constant c = cpg.getConstant(o.getIndex()); 566 if (! (c instanceof ConstantClass)){ 567 constraintViolated(o, "Expecting a CONSTANT_Class operand, but found a '"+c+"'."); 568 } 569 } 570 571 572 public void visitCHECKCAST(CHECKCAST o){ 573 indexValid(o, o.getIndex()); 574 Constant c = cpg.getConstant(o.getIndex()); 575 if (! (c instanceof ConstantClass)){ 576 constraintViolated(o, "Expecting a CONSTANT_Class operand, but found a '"+c+"'."); 577 } 578 } 579 580 581 public void visitNEW(NEW o){ 582 indexValid(o, o.getIndex()); 583 Constant c = cpg.getConstant(o.getIndex()); 584 if (! (c instanceof ConstantClass)){ 585 constraintViolated(o, "Expecting a CONSTANT_Class operand, but found a '"+c+"'."); 586 } 587 else{ 588 ConstantUtf8 cutf8 = (ConstantUtf8) (cpg.getConstant( ((ConstantClass) c).getNameIndex() )); 589 Type t = Type.getType("L"+cutf8.getBytes()+";"); 590 if (t instanceof ArrayType){ 591 constraintViolated(o, "NEW must not be used to create an array."); 592 } 593 } 594 595 } 596 597 598 public void visitMULTIANEWARRAY(MULTIANEWARRAY o){ 599 indexValid(o, o.getIndex()); 600 Constant c = cpg.getConstant(o.getIndex()); 601 if (! (c instanceof ConstantClass)){ 602 constraintViolated(o, "Expecting a CONSTANT_Class operand, but found a '"+c+"'."); 603 } 604 int dimensions2create = o.getDimensions(); 605 if (dimensions2create < 1){ 606 constraintViolated(o, "Number of dimensions to create must be greater than zero."); 607 } 608 Type t = o.getType(cpg); 609 if (t instanceof ArrayType){ 610 int dimensions = ((ArrayType) t).getDimensions(); 611 if (dimensions < dimensions2create){ 612 constraintViolated(o, "Not allowed to create array with more dimensions ('+dimensions2create+') than the one referenced by the CONSTANT_Class '"+t+"'."); 613 } 614 } 615 else{ 616 constraintViolated(o, "Expecting a CONSTANT_Class referencing an array type. [Constraint not found in The Java Virtual Machine Specification, Second Edition, 4.8.1]"); 617 } 618 } 619 620 621 public void visitANEWARRAY(ANEWARRAY o){ 622 indexValid(o, o.getIndex()); 623 Constant c = cpg.getConstant(o.getIndex()); 624 if (! (c instanceof ConstantClass)){ 625 constraintViolated(o, "Expecting a CONSTANT_Class operand, but found a '"+c+"'."); 626 } 627 Type t = o.getType(cpg); 628 if (t instanceof ArrayType){ 629 int dimensions = ((ArrayType) t).getDimensions(); 630 if (dimensions >= 255){ 631 constraintViolated(o, "Not allowed to create an array with more than 255 dimensions."); 632 } 633 } 634 } 635 636 637 public void visitNEWARRAY(NEWARRAY o){ 638 byte t = o.getTypecode(); 639 if (! ( (t == Constants.T_BOOLEAN) || 640 (t == Constants.T_CHAR) || 641 (t == Constants.T_FLOAT) || 642 (t == Constants.T_DOUBLE) || 643 (t == Constants.T_BYTE) || 644 (t == Constants.T_SHORT) || 645 (t == Constants.T_INT) || 646 (t == Constants.T_LONG) ) ){ 647 constraintViolated(o, "Illegal type code '+t+' for 'atype' operand."); 648 } 649 } 650 651 652 public void visitILOAD(ILOAD o){ 653 int idx = o.getIndex(); 654 if (idx < 0){ 655 constraintViolated(o, "Index '"+idx+"' must be non-negative."); 656 } 657 else{ 658 int maxminus1 = max_locals()-1; 659 if (idx > maxminus1){ 660 constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-1 '"+maxminus1+"'."); 661 } 662 } 663 } 664 665 666 public void visitFLOAD(FLOAD o){ 667 int idx = o.getIndex(); 668 if (idx < 0){ 669 constraintViolated(o, "Index '"+idx+"' must be non-negative."); 670 } 671 else{ 672 int maxminus1 = max_locals()-1; 673 if (idx > maxminus1){ 674 constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-1 '"+maxminus1+"'."); 675 } 676 } 677 } 678 679 680 public void visitALOAD(ALOAD o){ 681 int idx = o.getIndex(); 682 if (idx < 0){ 683 constraintViolated(o, "Index '"+idx+"' must be non-negative."); 684 } 685 else{ 686 int maxminus1 = max_locals()-1; 687 if (idx > maxminus1){ 688 constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-1 '"+maxminus1+"'."); 689 } 690 } 691 } 692 693 694 public void visitISTORE(ISTORE o){ 695 int idx = o.getIndex(); 696 if (idx < 0){ 697 constraintViolated(o, "Index '"+idx+"' must be non-negative."); 698 } 699 else{ 700 int maxminus1 = max_locals()-1; 701 if (idx > maxminus1){ 702 constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-1 '"+maxminus1+"'."); 703 } 704 } 705 } 706 707 708 public void visitFSTORE(FSTORE o){ 709 int idx = o.getIndex(); 710 if (idx < 0){ 711 constraintViolated(o, "Index '"+idx+"' must be non-negative."); 712 } 713 else{ 714 int maxminus1 = max_locals()-1; 715 if (idx > maxminus1){ 716 constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-1 '"+maxminus1+"'."); 717 } 718 } 719 } 720 721 722 public void visitASTORE(ASTORE o){ 723 int idx = o.getIndex(); 724 if (idx < 0){ 725 constraintViolated(o, "Index '"+idx+"' must be non-negative."); 726 } 727 else{ 728 int maxminus1 = max_locals()-1; 729 if (idx > maxminus1){ 730 constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-1 '"+maxminus1+"'."); 731 } 732 } 733 } 734 735 736 public void visitIINC(IINC o){ 737 int idx = o.getIndex(); 738 if (idx < 0){ 739 constraintViolated(o, "Index '"+idx+"' must be non-negative."); 740 } 741 else{ 742 int maxminus1 = max_locals()-1; 743 if (idx > maxminus1){ 744 constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-1 '"+maxminus1+"'."); 745 } 746 } 747 } 748 749 750 public void visitRET(RET o){ 751 int idx = o.getIndex(); 752 if (idx < 0){ 753 constraintViolated(o, "Index '"+idx+"' must be non-negative."); 754 } 755 else{ 756 int maxminus1 = max_locals()-1; 757 if (idx > maxminus1){ 758 constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-1 '"+maxminus1+"'."); 759 } 760 } 761 } 762 763 764 public void visitLLOAD(LLOAD o){ 765 int idx = o.getIndex(); 766 if (idx < 0){ 767 constraintViolated(o, "Index '"+idx+"' must be non-negative. [Constraint by JustIce as an analogon to the single-slot xLOAD/xSTORE instructions; may not happen anyway.]"); 768 } 769 else{ 770 int maxminus2 = max_locals()-2; 771 if (idx > maxminus2){ 772 constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-2 '"+maxminus2+"'."); 773 } 774 } 775 } 776 777 778 public void visitDLOAD(DLOAD o){ 779 int idx = o.getIndex(); 780 if (idx < 0){ 781 constraintViolated(o, "Index '"+idx+"' must be non-negative. [Constraint by JustIce as an analogon to the single-slot xLOAD/xSTORE instructions; may not happen anyway.]"); 782 } 783 else{ 784 int maxminus2 = max_locals()-2; 785 if (idx > maxminus2){ 786 constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-2 '"+maxminus2+"'."); 787 } 788 } 789 } 790 791 792 public void visitLSTORE(LSTORE o){ 793 int idx = o.getIndex(); 794 if (idx < 0){ 795 constraintViolated(o, "Index '"+idx+"' must be non-negative. [Constraint by JustIce as an analogon to the single-slot xLOAD/xSTORE instructions; may not happen anyway.]"); 796 } 797 else{ 798 int maxminus2 = max_locals()-2; 799 if (idx > maxminus2){ 800 constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-2 '"+maxminus2+"'."); 801 } 802 } 803 } 804 805 806 public void visitDSTORE(DSTORE o){ 807 int idx = o.getIndex(); 808 if (idx < 0){ 809 constraintViolated(o, "Index '"+idx+"' must be non-negative. [Constraint by JustIce as an analogon to the single-slot xLOAD/xSTORE instructions; may not happen anyway.]"); 810 } 811 else{ 812 int maxminus2 = max_locals()-2; 813 if (idx > maxminus2){ 814 constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-2 '"+maxminus2+"'."); 815 } 816 } 817 } 818 819 820 public void visitLOOKUPSWITCH(LOOKUPSWITCH o){ 821 int[] matchs = o.getMatchs(); 822 int max = Integer.MIN_VALUE; 823 for (int i=0; i<matchs.length; i++){ 824 if (matchs[i] == max && i != 0){ 825 constraintViolated(o, "Match '"+matchs[i]+"' occurs more than once."); 826 } 827 if (matchs[i] < max){ 828 constraintViolated(o, "Lookup table must be sorted but isn't."); 829 } 830 else{ 831 max = matchs[i]; 832 } 833 } 834 } 835 836 837 public void visitTABLESWITCH(TABLESWITCH o){ 838 } 841 842 843 public void visitPUTSTATIC(PUTSTATIC o){ 844 String field_name = o.getFieldName(cpg); 845 JavaClass jc = Repository.lookupClass(o.getClassType(cpg).getClassName()); 846 Field[] fields = jc.getFields(); 847 Field f = null; 848 for (int i=0; i<fields.length; i++){ 849 if (fields[i].getName().equals(field_name)){ 850 f = fields[i]; 851 break; 852 } 853 } 854 if (f == null){ 855 throw new AssertionViolatedException("Field not found?!?"); 856 } 857 858 if (f.isFinal()){ 859 if (!(myOwner.getClassName().equals(o.getClassType(cpg).getClassName()))){ 860 constraintViolated(o, "Referenced field '"+f+"' is final and must therefore be declared in the current class '"+myOwner.getClassName()+"' which is not the case: it is declared in '"+o.getClassType(cpg).getClassName()+"'."); 861 } 862 } 863 864 if (! (f.isStatic())){ 865 constraintViolated(o, "Referenced field '"+f+"' is not static which it should be."); 866 } 867 868 String meth_name = Repository.lookupClass(myOwner.getClassName()).getMethods()[method_no].getName(); 869 870 if ((!(jc.isClass())) && (!(meth_name.equals(Constants.STATIC_INITIALIZER_NAME)))){ 872 constraintViolated(o, "Interface field '"+f+"' must be set in a '"+Constants.STATIC_INITIALIZER_NAME+"' method."); 873 } 874 } 875 876 877 public void visitGETSTATIC(GETSTATIC o){ 878 String field_name = o.getFieldName(cpg); 879 JavaClass jc = Repository.lookupClass(o.getClassType(cpg).getClassName()); 880 Field[] fields = jc.getFields(); 881 Field f = null; 882 for (int i=0; i<fields.length; i++){ 883 if (fields[i].getName().equals(field_name)){ 884 f = fields[i]; 885 break; 886 } 887 } 888 if (f == null){ 889 throw new AssertionViolatedException("Field not found?!?"); 890 } 891 892 if (! (f.isStatic())){ 893 constraintViolated(o, "Referenced field '"+f+"' is not static which it should be."); 894 } 895 } 896 897 898 902 903 907 908 public void visitINVOKEINTERFACE(INVOKEINTERFACE o){ 909 String classname = o.getClassName(cpg); 914 JavaClass jc = Repository.lookupClass(classname); 915 Method[] ms = jc.getMethods(); 916 Method m = null; 917 for (int i=0; i<ms.length; i++){ 918 if ( (ms[i].getName().equals(o.getMethodName(cpg))) && 919 (Type.getReturnType(ms[i].getSignature()).equals(o.getReturnType(cpg))) && 920 (objarrayequals(Type.getArgumentTypes(ms[i].getSignature()), o.getArgumentTypes(cpg))) ){ 921 m = ms[i]; 922 break; 923 } 924 } 925 if (m == null){ 926 constraintViolated(o, "Referenced method '"+o.getMethodName(cpg)+"' with expected signature not found in class '"+jc.getClassName()+"'. The native verfier does allow the method to be declared in some superinterface, which the Java Virtual Machine Specification, Second Edition does not."); 927 } 928 if (jc.isClass()){ 929 constraintViolated(o, "Referenced class '"+jc.getClassName()+"' is a class, but not an interface as expected."); 930 } 931 } 932 933 934 public void visitINVOKESPECIAL(INVOKESPECIAL o){ 935 String classname = o.getClassName(cpg); 940 JavaClass jc = Repository.lookupClass(classname); 941 Method[] ms = jc.getMethods(); 942 Method m = null; 943 for (int i=0; i<ms.length; i++){ 944 if ( (ms[i].getName().equals(o.getMethodName(cpg))) && 945 (Type.getReturnType(ms[i].getSignature()).equals(o.getReturnType(cpg))) && 946 (objarrayequals(Type.getArgumentTypes(ms[i].getSignature()), o.getArgumentTypes(cpg))) ){ 947 m = ms[i]; 948 break; 949 } 950 } 951 if (m == null){ 952 constraintViolated(o, "Referenced method '"+o.getMethodName(cpg)+"' with expected signature not found in class '"+jc.getClassName()+"'. The native verfier does allow the method to be declared in some superclass or implemented interface, which the Java Virtual Machine Specification, Second Edition does not."); 953 } 954 955 JavaClass current = Repository.lookupClass(myOwner.getClassName()); 956 if (current.isSuper()){ 957 958 if ((Repository.instanceOf( current, jc )) && (!current.equals(jc))){ 959 960 if (! (o.getMethodName(cpg).equals(Constants.CONSTRUCTOR_NAME) )){ 961 963 int supidx = -1; 964 965 Method meth = null; 966 while (supidx != 0){ 967 supidx = current.getSuperclassNameIndex(); 968 current = Repository.lookupClass(current.getSuperclassName()); 969 970 Method[] meths = current.getMethods(); 971 for (int i=0; i<meths.length; i++){ 972 if ( (meths[i].getName().equals(o.getMethodName(cpg))) && 973 (Type.getReturnType(meths[i].getSignature()).equals(o.getReturnType(cpg))) && 974 (objarrayequals(Type.getArgumentTypes(meths[i].getSignature()), o.getArgumentTypes(cpg))) ){ 975 meth = meths[i]; 976 break; 977 } 978 } 979 if (meth != null) break; 980 } 981 if (meth == null){ 982 constraintViolated(o, "ACC_SUPER special lookup procedure not successful: method '"+o.getMethodName(cpg)+"' with proper signature not declared in superclass hierarchy."); 983 } 984 } 985 } 986 } 987 988 989 } 990 991 992 public void visitINVOKESTATIC(INVOKESTATIC o){ 993 String classname = o.getClassName(cpg); 998 JavaClass jc = Repository.lookupClass(classname); 999 Method[] ms = jc.getMethods(); 1000 Method m = null; 1001 for (int i=0; i<ms.length; i++){ 1002 if ( (ms[i].getName().equals(o.getMethodName(cpg))) && 1003 (Type.getReturnType(ms[i].getSignature()).equals(o.getReturnType(cpg))) && 1004 (objarrayequals(Type.getArgumentTypes(ms[i].getSignature()), o.getArgumentTypes(cpg))) ){ 1005 m = ms[i]; 1006 break; 1007 } 1008 } 1009 if (m == null){ 1010 constraintViolated(o, "Referenced method '"+o.getMethodName(cpg)+"' with expected signature not found in class '"+jc.getClassName()+"'. The native verifier possibly allows the method to be declared in some superclass or implemented interface, which the Java Virtual Machine Specification, Second Edition does not."); 1011 } 1012 1013 if (! (m.isStatic())){ constraintViolated(o, "Referenced method '"+o.getMethodName(cpg)+"' has ACC_STATIC unset."); 1015 } 1016 1017 } 1018 1019 1020 1021 public void visitINVOKEVIRTUAL(INVOKEVIRTUAL o){ 1022 String classname = o.getClassName(cpg); 1027 JavaClass jc = Repository.lookupClass(classname); 1028 Method[] ms = jc.getMethods(); 1029 Method m = null; 1030 for (int i=0; i<ms.length; i++){ 1031 if ( (ms[i].getName().equals(o.getMethodName(cpg))) && 1032 (Type.getReturnType(ms[i].getSignature()).equals(o.getReturnType(cpg))) && 1033 (objarrayequals(Type.getArgumentTypes(ms[i].getSignature()), o.getArgumentTypes(cpg))) ){ 1034 m = ms[i]; 1035 break; 1036 } 1037 } 1038 if (m == null){ 1039 constraintViolated(o, "Referenced method '"+o.getMethodName(cpg)+"' with expected signature not found in class '"+jc.getClassName()+"'. The native verfier does allow the method to be declared in some superclass or implemented interface, which the Java Virtual Machine Specification, Second Edition does not."); 1040 } 1041 if (! (jc.isClass())){ 1042 constraintViolated(o, "Referenced class '"+jc.getClassName()+"' is an interface, but not a class as expected."); 1043 } 1044 1045 } 1046 1047 1048 1050 1055 private boolean objarrayequals(Object [] o, Object [] p){ 1056 if (o.length != p.length){ 1057 return false; 1058 } 1059 1060 for (int i=0; i<o.length; i++){ 1061 if (! (o[i].equals(p[i])) ){ 1062 return false; 1063 } 1064 } 1065 1066 return true; 1067 } 1068 1069 } 1070} 1071 | Popular Tags |