1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 package org.apache.bcel.verifier.structurals; 19 20 21 import org.apache.bcel.Const; 22 import org.apache.bcel.Repository; 23 import org.apache.bcel.classfile.Constant; 24 import org.apache.bcel.classfile.ConstantClass; 25 import org.apache.bcel.classfile.ConstantDouble; 26 import org.apache.bcel.classfile.ConstantFieldref; 27 import org.apache.bcel.classfile.ConstantFloat; 28 import org.apache.bcel.classfile.ConstantInteger; 29 import org.apache.bcel.classfile.ConstantLong; 30 import org.apache.bcel.classfile.ConstantString; 31 import org.apache.bcel.classfile.Field; 32 import org.apache.bcel.classfile.JavaClass; 33 //CHECKSTYLE:OFF (there are lots of references!) 34 import org.apache.bcel.generic.*; 35 //CHECKSTYLE:ON 36 import org.apache.bcel.verifier.VerificationResult; 37 import org.apache.bcel.verifier.Verifier; 38 import org.apache.bcel.verifier.VerifierFactory; 39 import org.apache.bcel.verifier.exc.AssertionViolatedException; 40 import org.apache.bcel.verifier.exc.StructuralCodeConstraintException; 41 42 43 /** 44 * A Visitor class testing for valid preconditions of JVM instructions. 45 * The instance of this class will throw a StructuralCodeConstraintException 46 * instance if an instruction is visitXXX()ed which has preconditions that are 47 * not satisfied. 48 * TODO: Currently, the JVM's behaviour concerning monitors (MONITORENTER, 49 * MONITOREXIT) is not modeled in JustIce. 50 * 51 * @version $Id$ 52 * @see StructuralCodeConstraintException 53 */ 54 public class InstConstraintVisitor extends EmptyVisitor{ 55 56 private static final ObjectType GENERIC_ARRAY = ObjectType.getInstance(GenericArray.class.getName()); 57 58 /** 59 * The constructor. Constructs a new instance of this class. 60 */ InstConstraintVisitor()61 public InstConstraintVisitor() {} 62 63 /** 64 * The Execution Frame we're working on. 65 * 66 * @see #setFrame(Frame f) 67 * @see #locals() 68 * @see #stack() 69 */ 70 private Frame frame = null; 71 72 /** 73 * The ConstantPoolGen we're working on. 74 * 75 * @see #setConstantPoolGen(ConstantPoolGen cpg) 76 */ 77 private ConstantPoolGen cpg = null; 78 79 /** 80 * The MethodGen we're working on. 81 * 82 * @see #setMethodGen(MethodGen mg) 83 */ 84 private MethodGen mg = null; 85 86 /** 87 * The OperandStack we're working on. 88 * 89 * @see #setFrame(Frame f) 90 */ stack()91 private OperandStack stack() { 92 return frame.getStack(); 93 } 94 95 /** 96 * The LocalVariables we're working on. 97 * 98 * @see #setFrame(Frame f) 99 */ locals()100 private LocalVariables locals() { 101 return frame.getLocals(); 102 } 103 104 /** 105 * This method is called by the visitXXX() to notify the acceptor of this InstConstraintVisitor 106 * that a constraint violation has occured. This is done by throwing an instance of a 107 * StructuralCodeConstraintException. 108 * @throws StructuralCodeConstraintException always. 109 */ constraintViolated(final Instruction violator, final String description)110 private void constraintViolated(final Instruction violator, final String description) { 111 final String fq_classname = violator.getClass().getName(); 112 throw new StructuralCodeConstraintException( 113 "Instruction "+ fq_classname.substring(fq_classname.lastIndexOf('.')+1) +" constraint violated: " + description); 114 } 115 116 /** 117 * This returns the single instance of the InstConstraintVisitor class. 118 * To operate correctly, other values must have been set before actually 119 * using the instance. 120 * Use this method for performance reasons. 121 * 122 * @see #setConstantPoolGen(ConstantPoolGen cpg) 123 * @see #setMethodGen(MethodGen mg) 124 */ setFrame(final Frame f)125 public void setFrame(final Frame f) { // TODO could be package-protected? 126 this.frame = f; 127 //if (singleInstance.mg == null || singleInstance.cpg == null) 128 // throw new AssertionViolatedException("Forgot to set important values first."); 129 } 130 131 /** 132 * Sets the ConstantPoolGen instance needed for constraint 133 * checking prior to execution. 134 */ setConstantPoolGen(final ConstantPoolGen cpg)135 public void setConstantPoolGen(final ConstantPoolGen cpg) { // TODO could be package-protected? 136 this.cpg = cpg; 137 } 138 139 /** 140 * Sets the MethodGen instance needed for constraint 141 * checking prior to execution. 142 */ setMethodGen(final MethodGen mg)143 public void setMethodGen(final MethodGen mg) { 144 this.mg = mg; 145 } 146 147 /** 148 * Assures index is of type INT. 149 * @throws StructuralCodeConstraintException if the above constraint is not satisfied. 150 */ indexOfInt(final Instruction o, final Type index)151 private void indexOfInt(final Instruction o, final Type index) { 152 if (! index.equals(Type.INT)) { 153 constraintViolated(o, "The 'index' is not of type int but of type "+index+"."); 154 } 155 } 156 157 /** 158 * Assures the ReferenceType r is initialized (or Type.NULL). 159 * Formally, this means (!(r instanceof UninitializedObjectType)), because 160 * there are no uninitialized array types. 161 * @throws StructuralCodeConstraintException if the above constraint is not satisfied. 162 */ referenceTypeIsInitialized(final Instruction o, final ReferenceType r)163 private void referenceTypeIsInitialized(final Instruction o, final ReferenceType r) { 164 if (r instanceof UninitializedObjectType) { 165 constraintViolated(o, "Working on an uninitialized object '"+r+"'."); 166 } 167 } 168 169 /** Assures value is of type INT. */ valueOfInt(final Instruction o, final Type value)170 private void valueOfInt(final Instruction o, final Type value) { 171 if (! value.equals(Type.INT)) { 172 constraintViolated(o, "The 'value' is not of type int but of type "+value+"."); 173 } 174 } 175 176 /** 177 * Assures arrayref is of ArrayType or NULL; 178 * returns true if and only if arrayref is non-NULL. 179 * @throws StructuralCodeConstraintException if the above constraint is violated. 180 */ arrayrefOfArrayType(final Instruction o, final Type arrayref)181 private boolean arrayrefOfArrayType(final Instruction o, final Type arrayref) { 182 if (! ((arrayref instanceof ArrayType) || arrayref.equals(Type.NULL)) ) { 183 constraintViolated(o, "The 'arrayref' does not refer to an array but is of type "+arrayref+"."); 184 } 185 return arrayref instanceof ArrayType; 186 } 187 188 /***************************************************************/ 189 /* MISC */ 190 /***************************************************************/ 191 /** 192 * Ensures the general preconditions of an instruction that accesses the stack. 193 * This method is here because BCEL has no such superinterface for the stack 194 * accessing instructions; and there are funny unexpected exceptions in the 195 * semantices of the superinterfaces and superclasses provided. 196 * E.g. SWAP is a StackConsumer, but DUP_X1 is not a StackProducer. 197 * Therefore, this method is called by all StackProducer, StackConsumer, 198 * and StackInstruction instances via their visitXXX() method. 199 * Unfortunately, as the superclasses and superinterfaces overlap, some instructions 200 * cause this method to be called two or three times. [TODO: Fix this.] 201 * 202 * @see #visitStackConsumer(StackConsumer o) 203 * @see #visitStackProducer(StackProducer o) 204 * @see #visitStackInstruction(StackInstruction o) 205 */ _visitStackAccessor(final Instruction o)206 private void _visitStackAccessor(final Instruction o) { 207 final int consume = o.consumeStack(cpg); // Stack values are always consumed first; then produced. 208 if (consume > stack().slotsUsed()) { 209 constraintViolated(o, 210 "Cannot consume "+consume+" stack slots: only "+stack().slotsUsed()+" slot(s) left on stack!\nStack:\n"+stack()); 211 } 212 213 final int produce = o.produceStack(cpg) - o.consumeStack(cpg); // Stack values are always consumed first; then produced. 214 if ( produce + stack().slotsUsed() > stack().maxStack() ) { 215 constraintViolated(o, "Cannot produce "+produce+" stack slots: only "+(stack().maxStack()-stack().slotsUsed())+ 216 " free stack slot(s) left.\nStack:\n"+stack()); 217 } 218 } 219 220 /***************************************************************/ 221 /* "generic"visitXXXX methods where XXXX is an interface */ 222 /* therefore, we don't know the order of visiting; but we know */ 223 /* these methods are called before the visitYYYY methods below */ 224 /***************************************************************/ 225 226 /** 227 * Assures the generic preconditions of a LoadClass instance. 228 * The referenced class is loaded and pass2-verified. 229 */ 230 @Override visitLoadClass(final LoadClass o)231 public void visitLoadClass(final LoadClass o) { 232 final ObjectType t = o.getLoadClassType(cpg); 233 if (t != null) {// null means "no class is loaded" 234 final Verifier v = VerifierFactory.getVerifier(t.getClassName()); 235 final VerificationResult vr = v.doPass2(); 236 if (vr.getStatus() != VerificationResult.VERIFIED_OK) { 237 constraintViolated((Instruction) o, "Class '"+o.getLoadClassType(cpg).getClassName()+ 238 "' is referenced, but cannot be loaded and resolved: '"+vr+"'."); 239 } 240 } 241 } 242 243 /** 244 * Ensures the general preconditions of a StackConsumer instance. 245 */ 246 @Override visitStackConsumer(final StackConsumer o)247 public void visitStackConsumer(final StackConsumer o) { 248 _visitStackAccessor((Instruction) o); 249 } 250 251 /** 252 * Ensures the general preconditions of a StackProducer instance. 253 */ 254 @Override visitStackProducer(final StackProducer o)255 public void visitStackProducer(final StackProducer o) { 256 _visitStackAccessor((Instruction) o); 257 } 258 259 260 /***************************************************************/ 261 /* "generic" visitYYYY methods where YYYY is a superclass. */ 262 /* therefore, we know the order of visiting; we know */ 263 /* these methods are called after the visitXXXX methods above. */ 264 /***************************************************************/ 265 /** 266 * Ensures the general preconditions of a CPInstruction instance. 267 */ 268 @Override visitCPInstruction(final CPInstruction o)269 public void visitCPInstruction(final CPInstruction o) { 270 final int idx = o.getIndex(); 271 if ((idx < 0) || (idx >= cpg.getSize())) { 272 throw new AssertionViolatedException( 273 "Huh?! Constant pool index of instruction '"+o+"' illegal? Pass 3a should have checked this!"); 274 } 275 } 276 277 /** 278 * Ensures the general preconditions of a FieldInstruction instance. 279 */ 280 @Override visitFieldInstruction(final FieldInstruction o)281 public void visitFieldInstruction(final FieldInstruction o) { 282 // visitLoadClass(o) has been called before: Every FieldOrMethod 283 // implements LoadClass. 284 // visitCPInstruction(o) has been called before. 285 // A FieldInstruction may be: GETFIELD, GETSTATIC, PUTFIELD, PUTSTATIC 286 final Constant c = cpg.getConstant(o.getIndex()); 287 if (!(c instanceof ConstantFieldref)) { 288 constraintViolated(o, 289 "Index '"+o.getIndex()+"' should refer to a CONSTANT_Fieldref_info structure, but refers to '"+c+"'."); 290 } 291 // the o.getClassType(cpg) type has passed pass 2; see visitLoadClass(o). 292 final Type t = o.getType(cpg); 293 if (t instanceof ObjectType) { 294 final String name = ((ObjectType)t).getClassName(); 295 final Verifier v = VerifierFactory.getVerifier( name ); 296 final VerificationResult vr = v.doPass2(); 297 if (vr.getStatus() != VerificationResult.VERIFIED_OK) { 298 constraintViolated(o, "Class '"+name+"' is referenced, but cannot be loaded and resolved: '"+vr+"'."); 299 } 300 } 301 } 302 303 /** 304 * Ensures the general preconditions of an InvokeInstruction instance. 305 */ 306 @Override visitInvokeInstruction(final InvokeInstruction o)307 public void visitInvokeInstruction(final InvokeInstruction o) { 308 // visitLoadClass(o) has been called before: Every FieldOrMethod 309 // implements LoadClass. 310 // visitCPInstruction(o) has been called before. 311 //TODO 312 } 313 314 /** 315 * Ensures the general preconditions of a StackInstruction instance. 316 */ 317 @Override visitStackInstruction(final StackInstruction o)318 public void visitStackInstruction(final StackInstruction o) { 319 _visitStackAccessor(o); 320 } 321 322 /** 323 * Assures the generic preconditions of a LocalVariableInstruction instance. 324 * That is, the index of the local variable must be valid. 325 */ 326 @Override visitLocalVariableInstruction(final LocalVariableInstruction o)327 public void visitLocalVariableInstruction(final LocalVariableInstruction o) { 328 if (locals().maxLocals() <= (o.getType(cpg).getSize()==1? o.getIndex() : o.getIndex()+1) ) { 329 constraintViolated(o, "The 'index' is not a valid index into the local variable array."); 330 } 331 } 332 333 /** 334 * Assures the generic preconditions of a LoadInstruction instance. 335 */ 336 @Override visitLoadInstruction(final LoadInstruction o)337 public void visitLoadInstruction(final LoadInstruction o) { 338 //visitLocalVariableInstruction(o) is called before, because it is more generic. 339 340 // LOAD instructions must not read Type.UNKNOWN 341 if (locals().get(o.getIndex()) == Type.UNKNOWN) { 342 constraintViolated(o, "Read-Access on local variable "+o.getIndex()+" with unknown content."); 343 } 344 345 // LOAD instructions, two-slot-values at index N must have Type.UNKNOWN 346 // as a symbol for the higher halve at index N+1 347 // [suppose some instruction put an int at N+1--- our double at N is defective] 348 if (o.getType(cpg).getSize() == 2) { 349 if (locals().get(o.getIndex()+1) != Type.UNKNOWN) { 350 constraintViolated(o, 351 "Reading a two-locals value from local variables "+o.getIndex()+ 352 " and "+(o.getIndex()+1)+" where the latter one is destroyed."); 353 } 354 } 355 356 // LOAD instructions must read the correct type. 357 if (!(o instanceof ALOAD)) { 358 if (locals().get(o.getIndex()) != o.getType(cpg) ) { 359 constraintViolated(o,"Local Variable type and LOADing Instruction type mismatch: Local Variable: '"+ 360 locals().get(o.getIndex())+"'; Instruction type: '"+o.getType(cpg)+"'."); 361 } 362 } 363 else{ // we deal with an ALOAD 364 if (!(locals().get(o.getIndex()) instanceof ReferenceType)) { 365 constraintViolated(o, "Local Variable type and LOADing Instruction type mismatch: Local Variable: '"+ 366 locals().get(o.getIndex())+"'; Instruction expects a ReferenceType."); 367 } 368 // ALOAD __IS ALLOWED__ to put uninitialized objects onto the stack! 369 //referenceTypeIsInitialized(o, (ReferenceType) (locals().get(o.getIndex()))); 370 } 371 372 // LOAD instructions must have enough free stack slots. 373 if ((stack().maxStack() - stack().slotsUsed()) < o.getType(cpg).getSize()) { 374 constraintViolated(o, "Not enough free stack slots to load a '"+o.getType(cpg)+"' onto the OperandStack."); 375 } 376 } 377 378 /** 379 * Assures the generic preconditions of a StoreInstruction instance. 380 */ 381 @Override visitStoreInstruction(final StoreInstruction o)382 public void visitStoreInstruction(final StoreInstruction o) { 383 //visitLocalVariableInstruction(o) is called before, because it is more generic. 384 385 if (stack().isEmpty()) { // Don't bother about 1 or 2 stack slots used. This check is implicitly done below while type checking. 386 constraintViolated(o, "Cannot STORE: Stack to read from is empty."); 387 } 388 389 if ( !(o instanceof ASTORE) ) { 390 if (! (stack().peek() == o.getType(cpg)) ) {// the other xSTORE types are singletons in BCEL. 391 constraintViolated(o, "Stack top type and STOREing Instruction type mismatch: Stack top: '"+stack().peek()+ 392 "'; Instruction type: '"+o.getType(cpg)+"'."); 393 } 394 } 395 else{ // we deal with ASTORE 396 final Type stacktop = stack().peek(); 397 if ( (!(stacktop instanceof ReferenceType)) && (!(stacktop instanceof ReturnaddressType)) ) { 398 constraintViolated(o, "Stack top type and STOREing Instruction type mismatch: Stack top: '"+stack().peek()+ 399 "'; Instruction expects a ReferenceType or a ReturnadressType."); 400 } 401 //if (stacktop instanceof ReferenceType) { 402 // referenceTypeIsInitialized(o, (ReferenceType) stacktop); 403 //} 404 } 405 } 406 407 /** 408 * Assures the generic preconditions of a ReturnInstruction instance. 409 */ 410 @Override visitReturnInstruction(final ReturnInstruction o)411 public void visitReturnInstruction(final ReturnInstruction o) { 412 Type method_type = mg.getType(); 413 if (method_type == Type.BOOLEAN || 414 method_type == Type.BYTE || 415 method_type == Type.SHORT || 416 method_type == Type.CHAR) { 417 method_type = Type.INT; 418 } 419 420 if (o instanceof RETURN) { 421 if (method_type != Type.VOID) { 422 constraintViolated(o, "RETURN instruction in non-void method."); 423 } 424 else{ 425 return; 426 } 427 } 428 if (o instanceof ARETURN) { 429 if (method_type == Type.VOID) { 430 constraintViolated(o, "ARETURN instruction in void method."); 431 } 432 if (stack().peek() == Type.NULL) { 433 return; 434 } 435 if (! (stack().peek() instanceof ReferenceType)) { 436 constraintViolated(o, "Reference type expected on top of stack, but is: '"+stack().peek()+"'."); 437 } 438 referenceTypeIsInitialized(o, (ReferenceType) (stack().peek())); 439 //ReferenceType objectref = (ReferenceType) (stack().peek()); 440 // TODO: This can only be checked if using Staerk-et-al's "set of object types" instead of a 441 // "wider cast object type" created during verification. 442 //if (! (objectref.isAssignmentCompatibleWith(mg.getType())) ) { 443 // constraintViolated(o, "Type on stack top which should be returned is a '"+stack().peek()+ 444 // "' which is not assignment compatible with the return type of this method, '"+mg.getType()+"'."); 445 //} 446 } 447 else{ 448 if (! ( method_type.equals( stack().peek() ))) { 449 constraintViolated(o, "Current method has return type of '"+mg.getType()+"' expecting a '"+method_type+ 450 "' on top of the stack. But stack top is a '"+stack().peek()+"'."); 451 } 452 } 453 } 454 455 /***************************************************************/ 456 /* "special"visitXXXX methods for one type of instruction each */ 457 /***************************************************************/ 458 459 /** 460 * Ensures the specific preconditions of the said instruction. 461 */ 462 @Override visitAALOAD(final AALOAD o)463 public void visitAALOAD(final AALOAD o) { 464 final Type arrayref = stack().peek(1); 465 final Type index = stack().peek(0); 466 467 indexOfInt(o, index); 468 if (arrayrefOfArrayType(o, arrayref)) { 469 if (! (((ArrayType) arrayref).getElementType() instanceof ReferenceType)) { 470 constraintViolated(o, 471 "The 'arrayref' does not refer to an array with elements of a ReferenceType but to an array of "+ 472 ((ArrayType) arrayref).getElementType()+"."); 473 } 474 //referenceTypeIsInitialized(o, (ReferenceType) (((ArrayType) arrayref).getElementType())); 475 } 476 } 477 478 /** 479 * Ensures the specific preconditions of the said instruction. 480 */ 481 @Override visitAASTORE(final AASTORE o)482 public void visitAASTORE(final AASTORE o) { 483 final Type arrayref = stack().peek(2); 484 final Type index = stack().peek(1); 485 final Type value = stack().peek(0); 486 487 indexOfInt(o, index); 488 if (!(value instanceof ReferenceType)) { 489 constraintViolated(o, "The 'value' is not of a ReferenceType but of type "+value+"."); 490 }else{ 491 //referenceTypeIsInitialized(o, (ReferenceType) value); 492 } 493 // Don't bother further with "referenceTypeIsInitialized()", there are no arrays 494 // of an uninitialized object type. 495 if (arrayrefOfArrayType(o, arrayref)) { 496 if (! (((ArrayType) arrayref).getElementType() instanceof ReferenceType)) { 497 constraintViolated(o, "The 'arrayref' does not refer to an array with elements of a ReferenceType but to an array of "+ 498 ((ArrayType) arrayref).getElementType()+"."); 499 } 500 // No check for array element assignment compatibility. This is done at runtime. 501 } 502 } 503 504 /** 505 * Ensures the specific preconditions of the said instruction. 506 */ 507 @Override visitACONST_NULL(final ACONST_NULL o)508 public void visitACONST_NULL(final ACONST_NULL o) { 509 // Nothing needs to be done here. 510 } 511 512 /** 513 * Ensures the specific preconditions of the said instruction. 514 */ 515 @Override visitALOAD(final ALOAD o)516 public void visitALOAD(final ALOAD o) { 517 //visitLoadInstruction(LoadInstruction) is called before. 518 519 // Nothing else needs to be done here. 520 } 521 522 /** 523 * Ensures the specific preconditions of the said instruction. 524 */ 525 @Override visitANEWARRAY(final ANEWARRAY o)526 public void visitANEWARRAY(final ANEWARRAY o) { 527 if (!stack().peek().equals(Type.INT)) { 528 constraintViolated(o, "The 'count' at the stack top is not of type '"+Type.INT+"' but of type '"+stack().peek()+"'."); 529 // The runtime constant pool item at that index must be a symbolic reference to a class, 530 // array, or interface type. See Pass 3a. 531 } 532 } 533 534 /** 535 * Ensures the specific preconditions of the said instruction. 536 */ 537 @Override visitARETURN(final ARETURN o)538 public void visitARETURN(final ARETURN o) { 539 if (! (stack().peek() instanceof ReferenceType) ) { 540 constraintViolated(o, "The 'objectref' at the stack top is not of a ReferenceType but of type '"+stack().peek()+"'."); 541 } 542 final ReferenceType objectref = (ReferenceType) (stack().peek()); 543 referenceTypeIsInitialized(o, objectref); 544 545 // The check below should already done via visitReturnInstruction(ReturnInstruction), see there. 546 // It cannot be done using Staerk-et-al's "set of object types" instead of a 547 // "wider cast object type", anyway. 548 //if (! objectref.isAssignmentCompatibleWith(mg.getReturnType() )) { 549 // constraintViolated(o, "The 'objectref' type "+objectref+ 550 // " at the stack top is not assignment compatible with the return type '"+mg.getReturnType()+"' of the method."); 551 //} 552 } 553 554 /** 555 * Ensures the specific preconditions of the said instruction. 556 */ 557 @Override visitARRAYLENGTH(final ARRAYLENGTH o)558 public void visitARRAYLENGTH(final ARRAYLENGTH o) { 559 final Type arrayref = stack().peek(0); 560 arrayrefOfArrayType(o, arrayref); 561 } 562 563 /** 564 * Ensures the specific preconditions of the said instruction. 565 */ 566 @Override visitASTORE(final ASTORE o)567 public void visitASTORE(final ASTORE o) { 568 if (! ( (stack().peek() instanceof ReferenceType) || (stack().peek() instanceof ReturnaddressType) ) ) { 569 constraintViolated(o, "The 'objectref' is not of a ReferenceType or of ReturnaddressType but of "+stack().peek()+"."); 570 } 571 //if (stack().peek() instanceof ReferenceType) { 572 // referenceTypeIsInitialized(o, (ReferenceType) (stack().peek()) ); 573 //} 574 } 575 576 /** 577 * Ensures the specific preconditions of the said instruction. 578 */ 579 @Override visitATHROW(final ATHROW o)580 public void visitATHROW(final ATHROW o) { 581 try { 582 // It's stated that 'objectref' must be of a ReferenceType --- but since Throwable is 583 // not derived from an ArrayType, it follows that 'objectref' must be of an ObjectType or Type.NULL. 584 if (! ((stack().peek() instanceof ObjectType) || (stack().peek().equals(Type.NULL))) ) { 585 constraintViolated(o, "The 'objectref' is not of an (initialized) ObjectType but of type "+stack().peek()+"."); 586 } 587 588 // NULL is a subclass of every class, so to speak. 589 if (stack().peek().equals(Type.NULL)) { 590 return; 591 } 592 593 final ObjectType exc = (ObjectType) (stack().peek()); 594 final ObjectType throwable = (ObjectType) (Type.getType("Ljava/lang/Throwable;")); 595 if ( (! (exc.subclassOf(throwable)) ) && (! (exc.equals(throwable))) ) { 596 constraintViolated(o, 597 "The 'objectref' is not of class Throwable or of a subclass of Throwable, but of '"+stack().peek()+"'."); 598 } 599 } catch (final ClassNotFoundException e) { 600 // FIXME: maybe not the best way to handle this 601 throw new AssertionViolatedException("Missing class: " + e, e); 602 } 603 } 604 605 /** 606 * Ensures the specific preconditions of the said instruction. 607 */ 608 @Override visitBALOAD(final BALOAD o)609 public void visitBALOAD(final BALOAD o) { 610 final Type arrayref = stack().peek(1); 611 final Type index = stack().peek(0); 612 indexOfInt(o, index); 613 if (arrayrefOfArrayType(o, arrayref)) { 614 if (! ( (((ArrayType) arrayref).getElementType().equals(Type.BOOLEAN)) || 615 (((ArrayType) arrayref).getElementType().equals(Type.BYTE)) ) ) { 616 constraintViolated(o, 617 "The 'arrayref' does not refer to an array with elements of a Type.BYTE or Type.BOOLEAN but to an array of '"+ 618 ((ArrayType) arrayref).getElementType()+"'."); 619 } 620 } 621 } 622 623 /** 624 * Ensures the specific preconditions of the said instruction. 625 */ 626 @Override visitBASTORE(final BASTORE o)627 public void visitBASTORE(final BASTORE o) { 628 final Type arrayref = stack().peek(2); 629 final Type index = stack().peek(1); 630 final Type value = stack().peek(0); 631 632 indexOfInt(o, index); 633 valueOfInt(o, value); 634 if (arrayrefOfArrayType(o, arrayref)) { 635 if (! ( (((ArrayType) arrayref).getElementType().equals(Type.BOOLEAN)) || 636 (((ArrayType) arrayref).getElementType().equals(Type.BYTE)) ) ) { 637 constraintViolated(o, 638 "The 'arrayref' does not refer to an array with elements of a Type.BYTE or Type.BOOLEAN but to an array of '"+ 639 ((ArrayType) arrayref).getElementType()+"'."); 640 } 641 } 642 } 643 644 /** 645 * Ensures the specific preconditions of the said instruction. 646 */ 647 @Override visitBIPUSH(final BIPUSH o)648 public void visitBIPUSH(final BIPUSH o) { 649 // Nothing to do... 650 } 651 652 /** 653 * Ensures the specific preconditions of the said instruction. 654 */ 655 @Override visitBREAKPOINT(final BREAKPOINT o)656 public void visitBREAKPOINT(final BREAKPOINT o) { 657 throw new AssertionViolatedException( 658 "In this JustIce verification pass there should not occur an illegal instruction such as BREAKPOINT."); 659 } 660 661 /** 662 * Ensures the specific preconditions of the said instruction. 663 */ 664 @Override visitCALOAD(final CALOAD o)665 public void visitCALOAD(final CALOAD o) { 666 final Type arrayref = stack().peek(1); 667 final Type index = stack().peek(0); 668 669 indexOfInt(o, index); 670 arrayrefOfArrayType(o, arrayref); 671 } 672 673 /** 674 * Ensures the specific preconditions of the said instruction. 675 */ 676 @Override visitCASTORE(final CASTORE o)677 public void visitCASTORE(final CASTORE o) { 678 final Type arrayref = stack().peek(2); 679 final Type index = stack().peek(1); 680 final Type value = stack().peek(0); 681 682 indexOfInt(o, index); 683 valueOfInt(o, value); 684 if (arrayrefOfArrayType(o, arrayref)) { 685 if (! ((ArrayType) arrayref).getElementType().equals(Type.CHAR) ) { 686 constraintViolated(o, "The 'arrayref' does not refer to an array with elements of type char but to an array of type "+ 687 ((ArrayType) arrayref).getElementType()+"."); 688 } 689 } 690 } 691 692 /** 693 * Ensures the specific preconditions of the said instruction. 694 */ 695 @Override visitCHECKCAST(final CHECKCAST o)696 public void visitCHECKCAST(final CHECKCAST o) { 697 // The objectref must be of type reference. 698 final Type objectref = stack().peek(0); 699 if (!(objectref instanceof ReferenceType)) { 700 constraintViolated(o, "The 'objectref' is not of a ReferenceType but of type "+objectref+"."); 701 } 702 //else{ 703 // referenceTypeIsInitialized(o, (ReferenceType) objectref); 704 //} 705 // The unsigned indexbyte1 and indexbyte2 are used to construct an index into the runtime constant pool of the 706 // current class (�3.6), where the value of the index is (indexbyte1 << 8) | indexbyte2. The runtime constant 707 // pool item at the index must be a symbolic reference to a class, array, or interface type. 708 final Constant c = cpg.getConstant(o.getIndex()); 709 if (! (c instanceof ConstantClass)) { 710 constraintViolated(o, "The Constant at 'index' is not a ConstantClass, but '"+c+"'."); 711 } 712 } 713 714 /** 715 * Ensures the specific preconditions of the said instruction. 716 */ 717 @Override visitD2F(final D2F o)718 public void visitD2F(final D2F o) { 719 if (stack().peek() != Type.DOUBLE) { 720 constraintViolated(o, "The value at the stack top is not of type 'double', but of type '"+stack().peek()+"'."); 721 } 722 } 723 724 /** 725 * Ensures the specific preconditions of the said instruction. 726 */ 727 @Override visitD2I(final D2I o)728 public void visitD2I(final D2I o) { 729 if (stack().peek() != Type.DOUBLE) { 730 constraintViolated(o, "The value at the stack top is not of type 'double', but of type '"+stack().peek()+"'."); 731 } 732 } 733 734 /** 735 * Ensures the specific preconditions of the said instruction. 736 */ 737 @Override visitD2L(final D2L o)738 public void visitD2L(final D2L o) { 739 if (stack().peek() != Type.DOUBLE) { 740 constraintViolated(o, "The value at the stack top is not of type 'double', but of type '"+stack().peek()+"'."); 741 } 742 } 743 744 /** 745 * Ensures the specific preconditions of the said instruction. 746 */ 747 @Override visitDADD(final DADD o)748 public void visitDADD(final DADD o) { 749 if (stack().peek() != Type.DOUBLE) { 750 constraintViolated(o, "The value at the stack top is not of type 'double', but of type '"+stack().peek()+"'."); 751 } 752 if (stack().peek(1) != Type.DOUBLE) { 753 constraintViolated(o, "The value at the stack next-to-top is not of type 'double', but of type '"+stack().peek(1)+"'."); 754 } 755 } 756 757 /** 758 * Ensures the specific preconditions of the said instruction. 759 */ 760 @Override visitDALOAD(final DALOAD o)761 public void visitDALOAD(final DALOAD o) { 762 indexOfInt(o, stack().peek()); 763 if (stack().peek(1) == Type.NULL) { 764 return; 765 } 766 if (! (stack().peek(1) instanceof ArrayType)) { 767 constraintViolated(o, "Stack next-to-top must be of type double[] but is '"+stack().peek(1)+"'."); 768 } 769 final Type t = ((ArrayType) (stack().peek(1))).getBasicType(); 770 if (t != Type.DOUBLE) { 771 constraintViolated(o, "Stack next-to-top must be of type double[] but is '"+stack().peek(1)+"'."); 772 } 773 } 774 775 /** 776 * Ensures the specific preconditions of the said instruction. 777 */ 778 @Override visitDASTORE(final DASTORE o)779 public void visitDASTORE(final DASTORE o) { 780 if (stack().peek() != Type.DOUBLE) { 781 constraintViolated(o, "The value at the stack top is not of type 'double', but of type '"+stack().peek()+"'."); 782 } 783 indexOfInt(o, stack().peek(1)); 784 if (stack().peek(2) == Type.NULL) { 785 return; 786 } 787 if (! (stack().peek(2) instanceof ArrayType)) { 788 constraintViolated(o, "Stack next-to-next-to-top must be of type double[] but is '"+stack().peek(2)+"'."); 789 } 790 final Type t = ((ArrayType) (stack().peek(2))).getBasicType(); 791 if (t != Type.DOUBLE) { 792 constraintViolated(o, "Stack next-to-next-to-top must be of type double[] but is '"+stack().peek(2)+"'."); 793 } 794 } 795 796 /** 797 * Ensures the specific preconditions of the said instruction. 798 */ 799 @Override visitDCMPG(final DCMPG o)800 public void visitDCMPG(final DCMPG o) { 801 if (stack().peek() != Type.DOUBLE) { 802 constraintViolated(o, "The value at the stack top is not of type 'double', but of type '"+stack().peek()+"'."); 803 } 804 if (stack().peek(1) != Type.DOUBLE) { 805 constraintViolated(o, "The value at the stack next-to-top is not of type 'double', but of type '"+stack().peek(1)+"'."); 806 } 807 } 808 809 /** 810 * Ensures the specific preconditions of the said instruction. 811 */ 812 @Override visitDCMPL(final DCMPL o)813 public void visitDCMPL(final DCMPL o) { 814 if (stack().peek() != Type.DOUBLE) { 815 constraintViolated(o, "The value at the stack top is not of type 'double', but of type '"+stack().peek()+"'."); 816 } 817 if (stack().peek(1) != Type.DOUBLE) { 818 constraintViolated(o, "The value at the stack next-to-top is not of type 'double', but of type '"+stack().peek(1)+"'."); 819 } 820 } 821 822 /** 823 * Ensures the specific preconditions of the said instruction. 824 */ 825 @Override visitDCONST(final DCONST o)826 public void visitDCONST(final DCONST o) { 827 // There's nothing to be done here. 828 } 829 830 /** 831 * Ensures the specific preconditions of the said instruction. 832 */ 833 @Override visitDDIV(final DDIV o)834 public void visitDDIV(final DDIV o) { 835 if (stack().peek() != Type.DOUBLE) { 836 constraintViolated(o, "The value at the stack top is not of type 'double', but of type '"+stack().peek()+"'."); 837 } 838 if (stack().peek(1) != Type.DOUBLE) { 839 constraintViolated(o, "The value at the stack next-to-top is not of type 'double', but of type '"+stack().peek(1)+"'."); 840 } 841 } 842 843 /** 844 * Ensures the specific preconditions of the said instruction. 845 */ 846 @Override visitDLOAD(final DLOAD o)847 public void visitDLOAD(final DLOAD o) { 848 //visitLoadInstruction(LoadInstruction) is called before. 849 850 // Nothing else needs to be done here. 851 } 852 853 /** 854 * Ensures the specific preconditions of the said instruction. 855 */ 856 @Override visitDMUL(final DMUL o)857 public void visitDMUL(final DMUL o) { 858 if (stack().peek() != Type.DOUBLE) { 859 constraintViolated(o, "The value at the stack top is not of type 'double', but of type '"+stack().peek()+"'."); 860 } 861 if (stack().peek(1) != Type.DOUBLE) { 862 constraintViolated(o, "The value at the stack next-to-top is not of type 'double', but of type '"+stack().peek(1)+"'."); 863 } 864 } 865 866 /** 867 * Ensures the specific preconditions of the said instruction. 868 */ 869 @Override visitDNEG(final DNEG o)870 public void visitDNEG(final DNEG o) { 871 if (stack().peek() != Type.DOUBLE) { 872 constraintViolated(o, "The value at the stack top is not of type 'double', but of type '"+stack().peek()+"'."); 873 } 874 } 875 876 /** 877 * Ensures the specific preconditions of the said instruction. 878 */ 879 @Override visitDREM(final DREM o)880 public void visitDREM(final DREM o) { 881 if (stack().peek() != Type.DOUBLE) { 882 constraintViolated(o, "The value at the stack top is not of type 'double', but of type '"+stack().peek()+"'."); 883 } 884 if (stack().peek(1) != Type.DOUBLE) { 885 constraintViolated(o, "The value at the stack next-to-top is not of type 'double', but of type '"+stack().peek(1)+"'."); 886 } 887 } 888 889 /** 890 * Ensures the specific preconditions of the said instruction. 891 */ 892 @Override visitDRETURN(final DRETURN o)893 public void visitDRETURN(final DRETURN o) { 894 if (stack().peek() != Type.DOUBLE) { 895 constraintViolated(o, "The value at the stack top is not of type 'double', but of type '"+stack().peek()+"'."); 896 } 897 } 898 899 /** 900 * Ensures the specific preconditions of the said instruction. 901 */ 902 @Override visitDSTORE(final DSTORE o)903 public void visitDSTORE(final DSTORE o) { 904 //visitStoreInstruction(StoreInstruction) is called before. 905 906 // Nothing else needs to be done here. 907 } 908 909 /** 910 * Ensures the specific preconditions of the said instruction. 911 */ 912 @Override visitDSUB(final DSUB o)913 public void visitDSUB(final DSUB o) { 914 if (stack().peek() != Type.DOUBLE) { 915 constraintViolated(o, "The value at the stack top is not of type 'double', but of type '"+stack().peek()+"'."); 916 } 917 if (stack().peek(1) != Type.DOUBLE) { 918 constraintViolated(o, "The value at the stack next-to-top is not of type 'double', but of type '"+stack().peek(1)+"'."); 919 } 920 } 921 922 /** 923 * Ensures the specific preconditions of the said instruction. 924 */ 925 @Override visitDUP(final DUP o)926 public void visitDUP(final DUP o) { 927 if (stack().peek().getSize() != 1) { 928 constraintViolated(o, "Won't DUP type on stack top '"+stack().peek()+ 929 "' because it must occupy exactly one slot, not '"+stack().peek().getSize()+"'."); 930 } 931 } 932 933 /** 934 * Ensures the specific preconditions of the said instruction. 935 */ 936 @Override visitDUP_X1(final DUP_X1 o)937 public void visitDUP_X1(final DUP_X1 o) { 938 if (stack().peek().getSize() != 1) { 939 constraintViolated(o, 940 "Type on stack top '"+stack().peek()+"' should occupy exactly one slot, not '"+stack().peek().getSize()+"'."); 941 } 942 if (stack().peek(1).getSize() != 1) { 943 constraintViolated(o, 944 "Type on stack next-to-top '"+stack().peek(1)+ 945 "' should occupy exactly one slot, not '"+stack().peek(1).getSize()+"'."); 946 } 947 } 948 949 /** 950 * Ensures the specific preconditions of the said instruction. 951 */ 952 @Override visitDUP_X2(final DUP_X2 o)953 public void visitDUP_X2(final DUP_X2 o) { 954 if (stack().peek().getSize() != 1) { 955 constraintViolated(o, 956 "Stack top type must be of size 1, but is '"+stack().peek()+"' of size '"+stack().peek().getSize()+"'."); 957 } 958 if (stack().peek(1).getSize() == 2) { 959 return; // Form 2, okay. 960 } 961 //stack().peek(1).getSize == 1. 962 if (stack().peek(2).getSize() != 1) { 963 constraintViolated(o, 964 "If stack top's size is 1 and stack next-to-top's size is 1,"+ 965 " stack next-to-next-to-top's size must also be 1, but is: '"+ 966 stack().peek(2)+"' of size '"+stack().peek(2).getSize()+"'."); 967 } 968 } 969 970 /** 971 * Ensures the specific preconditions of the said instruction. 972 */ 973 @Override visitDUP2(final DUP2 o)974 public void visitDUP2(final DUP2 o) { 975 if (stack().peek().getSize() == 2) { 976 return; // Form 2, okay. 977 } 978 //stack().peek().getSize() == 1. 979 if (stack().peek(1).getSize() != 1) { 980 constraintViolated(o, 981 "If stack top's size is 1, then stack next-to-top's size must also be 1. But it is '"+stack().peek(1)+ 982 "' of size '"+stack().peek(1).getSize()+"'."); 983 } 984 } 985 986 /** 987 * Ensures the specific preconditions of the said instruction. 988 */ 989 @Override visitDUP2_X1(final DUP2_X1 o)990 public void visitDUP2_X1(final DUP2_X1 o) { 991 if (stack().peek().getSize() == 2) { 992 if (stack().peek(1).getSize() != 1) { 993 constraintViolated(o, "If stack top's size is 2, then stack next-to-top's size must be 1. But it is '"+ 994 stack().peek(1)+"' of size '"+stack().peek(1).getSize()+"'."); 995 } 996 else{ 997 return; // Form 2 998 } 999 } 1000 else{ // stack top is of size 1 1001 if ( stack().peek(1).getSize() != 1 ) { 1002 constraintViolated(o, "If stack top's size is 1, then stack next-to-top's size must also be 1. But it is '"+ 1003 stack().peek(1)+"' of size '"+stack().peek(1).getSize()+"'."); 1004 } 1005 if ( stack().peek(2).getSize() != 1 ) { 1006 constraintViolated(o, "If stack top's size is 1, then stack next-to-next-to-top's size must also be 1. But it is '"+ 1007 stack().peek(2)+"' of size '"+stack().peek(2).getSize()+"'."); 1008 } 1009 } 1010 } 1011 1012 /** 1013 * Ensures the specific preconditions of the said instruction. 1014 */ 1015 @Override visitDUP2_X2(final DUP2_X2 o)1016 public void visitDUP2_X2(final DUP2_X2 o) { 1017 1018 if (stack().peek(0).getSize() == 2) { 1019 if (stack().peek(1).getSize() == 2) { 1020 return; // Form 4 1021 } 1022 // stack top size is 2, next-to-top's size is 1 1023 if ( stack().peek(2).getSize() != 1 ) { 1024 constraintViolated(o, "If stack top's size is 2 and stack-next-to-top's size is 1,"+ 1025 " then stack next-to-next-to-top's size must also be 1. But it is '"+stack().peek(2)+ 1026 "' of size '"+stack().peek(2).getSize()+"'."); 1027 } 1028 else{ 1029 return; // Form 2 1030 } 1031 } 1032 else{// stack top is of size 1 1033 if (stack().peek(1).getSize() == 1) { 1034 if ( stack().peek(2).getSize() == 2 ) { 1035 return; // Form 3 1036 } 1037 if ( stack().peek(3).getSize() == 1) { 1038 return; // Form 1 1039 } 1040 } 1041 } 1042 constraintViolated(o, "The operand sizes on the stack do not match any of the four forms of usage of this instruction."); 1043 } 1044 1045 /** 1046 * Ensures the specific preconditions of the said instruction. 1047 */ 1048 @Override visitF2D(final F2D o)1049 public void visitF2D(final F2D o) { 1050 if (stack().peek() != Type.FLOAT) { 1051 constraintViolated(o, "The value at the stack top is not of type 'float', but of type '"+stack().peek()+"'."); 1052 } 1053 } 1054 1055 /** 1056 * Ensures the specific preconditions of the said instruction. 1057 */ 1058 @Override visitF2I(final F2I o)1059 public void visitF2I(final F2I o) { 1060 if (stack().peek() != Type.FLOAT) { 1061 constraintViolated(o, "The value at the stack top is not of type 'float', but of type '"+stack().peek()+"'."); 1062 } 1063 } 1064 1065 /** 1066 * Ensures the specific preconditions of the said instruction. 1067 */ 1068 @Override visitF2L(final F2L o)1069 public void visitF2L(final F2L o) { 1070 if (stack().peek() != Type.FLOAT) { 1071 constraintViolated(o, "The value at the stack top is not of type 'float', but of type '"+stack().peek()+"'."); 1072 } 1073 } 1074 1075 /** 1076 * Ensures the specific preconditions of the said instruction. 1077 */ 1078 @Override visitFADD(final FADD o)1079 public void visitFADD(final FADD o) { 1080 if (stack().peek() != Type.FLOAT) { 1081 constraintViolated(o, "The value at the stack top is not of type 'float', but of type '"+stack().peek()+"'."); 1082 } 1083 if (stack().peek(1) != Type.FLOAT) { 1084 constraintViolated(o, "The value at the stack next-to-top is not of type 'float', but of type '"+stack().peek(1)+"'."); 1085 } 1086 } 1087 1088 /** 1089 * Ensures the specific preconditions of the said instruction. 1090 */ 1091 @Override visitFALOAD(final FALOAD o)1092 public void visitFALOAD(final FALOAD o) { 1093 indexOfInt(o, stack().peek()); 1094 if (stack().peek(1) == Type.NULL) { 1095 return; 1096 } 1097 if (! (stack().peek(1) instanceof ArrayType)) { 1098 constraintViolated(o, "Stack next-to-top must be of type float[] but is '"+stack().peek(1)+"'."); 1099 } 1100 final Type t = ((ArrayType) (stack().peek(1))).getBasicType(); 1101 if (t != Type.FLOAT) { 1102 constraintViolated(o, "Stack next-to-top must be of type float[] but is '"+stack().peek(1)+"'."); 1103 } 1104 } 1105 1106 /** 1107 * Ensures the specific preconditions of the said instruction. 1108 */ 1109 @Override visitFASTORE(final FASTORE o)1110 public void visitFASTORE(final FASTORE o) { 1111 if (stack().peek() != Type.FLOAT) { 1112 constraintViolated(o, "The value at the stack top is not of type 'float', but of type '"+stack().peek()+"'."); 1113 } 1114 indexOfInt(o, stack().peek(1)); 1115 if (stack().peek(2) == Type.NULL) { 1116 return; 1117 } 1118 if (! (stack().peek(2) instanceof ArrayType)) { 1119 constraintViolated(o, "Stack next-to-next-to-top must be of type float[] but is '"+stack().peek(2)+"'."); 1120 } 1121 final Type t = ((ArrayType) (stack().peek(2))).getBasicType(); 1122 if (t != Type.FLOAT) { 1123 constraintViolated(o, "Stack next-to-next-to-top must be of type float[] but is '"+stack().peek(2)+"'."); 1124 } 1125 } 1126 1127 /** 1128 * Ensures the specific preconditions of the said instruction. 1129 */ 1130 @Override visitFCMPG(final FCMPG o)1131 public void visitFCMPG(final FCMPG o) { 1132 if (stack().peek() != Type.FLOAT) { 1133 constraintViolated(o, "The value at the stack top is not of type 'float', but of type '"+stack().peek()+"'."); 1134 } 1135 if (stack().peek(1) != Type.FLOAT) { 1136 constraintViolated(o, "The value at the stack next-to-top is not of type 'float', but of type '"+stack().peek(1)+"'."); 1137 } 1138 } 1139 1140 /** 1141 * Ensures the specific preconditions of the said instruction. 1142 */ 1143 @Override visitFCMPL(final FCMPL o)1144 public void visitFCMPL(final FCMPL o) { 1145 if (stack().peek() != Type.FLOAT) { 1146 constraintViolated(o, "The value at the stack top is not of type 'float', but of type '"+stack().peek()+"'."); 1147 } 1148 if (stack().peek(1) != Type.FLOAT) { 1149 constraintViolated(o, "The value at the stack next-to-top is not of type 'float', but of type '"+stack().peek(1)+"'."); 1150 } 1151 } 1152 1153 /** 1154 * Ensures the specific preconditions of the said instruction. 1155 */ 1156 @Override visitFCONST(final FCONST o)1157 public void visitFCONST(final FCONST o) { 1158 // nothing to do here. 1159 } 1160 1161 /** 1162 * Ensures the specific preconditions of the said instruction. 1163 */ 1164 @Override visitFDIV(final FDIV o)1165 public void visitFDIV(final FDIV o) { 1166 if (stack().peek() != Type.FLOAT) { 1167 constraintViolated(o, "The value at the stack top is not of type 'float', but of type '"+stack().peek()+"'."); 1168 } 1169 if (stack().peek(1) != Type.FLOAT) { 1170 constraintViolated(o, "The value at the stack next-to-top is not of type 'float', but of type '"+stack().peek(1)+"'."); 1171 } 1172 } 1173 1174 /** 1175 * Ensures the specific preconditions of the said instruction. 1176 */ 1177 @Override visitFLOAD(final FLOAD o)1178 public void visitFLOAD(final FLOAD o) { 1179 //visitLoadInstruction(LoadInstruction) is called before. 1180 1181 // Nothing else needs to be done here. 1182 } 1183 1184 /** 1185 * Ensures the specific preconditions of the said instruction. 1186 */ 1187 @Override visitFMUL(final FMUL o)1188 public void visitFMUL(final FMUL o) { 1189 if (stack().peek() != Type.FLOAT) { 1190 constraintViolated(o, "The value at the stack top is not of type 'float', but of type '"+stack().peek()+"'."); 1191 } 1192 if (stack().peek(1) != Type.FLOAT) { 1193 constraintViolated(o, "The value at the stack next-to-top is not of type 'float', but of type '"+stack().peek(1)+"'."); 1194 } 1195 } 1196 1197 /** 1198 * Ensures the specific preconditions of the said instruction. 1199 */ 1200 @Override visitFNEG(final FNEG o)1201 public void visitFNEG(final FNEG o) { 1202 if (stack().peek() != Type.FLOAT) { 1203 constraintViolated(o, "The value at the stack top is not of type 'float', but of type '"+stack().peek()+"'."); 1204 } 1205 } 1206 1207 /** 1208 * Ensures the specific preconditions of the said instruction. 1209 */ 1210 @Override visitFREM(final FREM o)1211 public void visitFREM(final FREM o) { 1212 if (stack().peek() != Type.FLOAT) { 1213 constraintViolated(o, "The value at the stack top is not of type 'float', but of type '"+stack().peek()+"'."); 1214 } 1215 if (stack().peek(1) != Type.FLOAT) { 1216 constraintViolated(o, "The value at the stack next-to-top is not of type 'float', but of type '"+stack().peek(1)+"'."); 1217 } 1218 } 1219 1220 /** 1221 * Ensures the specific preconditions of the said instruction. 1222 */ 1223 @Override visitFRETURN(final FRETURN o)1224 public void visitFRETURN(final FRETURN o) { 1225 if (stack().peek() != Type.FLOAT) { 1226 constraintViolated(o, "The value at the stack top is not of type 'float', but of type '"+stack().peek()+"'."); 1227 } 1228 } 1229 1230 /** 1231 * Ensures the specific preconditions of the said instruction. 1232 */ 1233 @Override visitFSTORE(final FSTORE o)1234 public void visitFSTORE(final FSTORE o) { 1235 //visitStoreInstruction(StoreInstruction) is called before. 1236 1237 // Nothing else needs to be done here. 1238 } 1239 1240 /** 1241 * Ensures the specific preconditions of the said instruction. 1242 */ 1243 @Override visitFSUB(final FSUB o)1244 public void visitFSUB(final FSUB o) { 1245 if (stack().peek() != Type.FLOAT) { 1246 constraintViolated(o, "The value at the stack top is not of type 'float', but of type '"+stack().peek()+"'."); 1247 } 1248 if (stack().peek(1) != Type.FLOAT) { 1249 constraintViolated(o, "The value at the stack next-to-top is not of type 'float', but of type '"+stack().peek(1)+"'."); 1250 } 1251 } 1252 getObjectType(final FieldInstruction o)1253 private ObjectType getObjectType(final FieldInstruction o) { 1254 final ReferenceType rt = o.getReferenceType(cpg); 1255 if(rt instanceof ObjectType) { 1256 return (ObjectType)rt; 1257 } 1258 constraintViolated(o, "expecting ObjectType but got "+rt); 1259 return null; 1260 } 1261 1262 /** 1263 * Ensures the specific preconditions of the said instruction. 1264 */ 1265 @Override visitGETFIELD(final GETFIELD o)1266 public void visitGETFIELD(final GETFIELD o) { 1267 try { 1268 final Type objectref = stack().peek(); 1269 if (! ( (objectref instanceof ObjectType) || (objectref == Type.NULL) ) ) { 1270 constraintViolated(o, "Stack top should be an object reference that's not an array reference, but is '"+objectref+"'."); 1271 } 1272 1273 final String field_name = o.getFieldName(cpg); 1274 1275 final JavaClass jc = Repository.lookupClass(getObjectType(o).getClassName()); 1276 Field[] fields = jc.getFields(); 1277 Field f = null; 1278 for (final Field field : fields) { 1279 if (field.getName().equals(field_name)) { 1280 final Type f_type = Type.getType(field.getSignature()); 1281 final Type o_type = o.getType(cpg); 1282 /* TODO: Check if assignment compatibility is sufficient. 1283 * What does Sun do? 1284 */ 1285 if (f_type.equals(o_type)) { 1286 f = field; 1287 break; 1288 } 1289 } 1290 } 1291 1292 if (f == null) { 1293 final JavaClass[] superclasses = jc.getSuperClasses(); 1294 outer: 1295 for (final JavaClass superclass : superclasses) { 1296 fields = superclass.getFields(); 1297 for (final Field field : fields) { 1298 if (field.getName().equals(field_name)) { 1299 final Type f_type = Type.getType(field.getSignature()); 1300 final Type o_type = o.getType(cpg); 1301 if (f_type.equals(o_type)) { 1302 f = field; 1303 if ((f.getAccessFlags() & (Const.ACC_PUBLIC | Const.ACC_PROTECTED)) == 0) { 1304 f = null; 1305 } 1306 break outer; 1307 } 1308 } 1309 } 1310 } 1311 if (f == null) { 1312 throw new AssertionViolatedException("Field '" + field_name + "' not found in " + jc.getClassName()); 1313 } 1314 } 1315 1316 if (f.isProtected()) { 1317 final ObjectType classtype = getObjectType(o); 1318 final ObjectType curr = ObjectType.getInstance(mg.getClassName()); 1319 1320 if ( classtype.equals(curr) || 1321 curr.subclassOf(classtype) ) { 1322 final Type t = stack().peek(); 1323 if (t == Type.NULL) { 1324 return; 1325 } 1326 if (! (t instanceof ObjectType) ) { 1327 constraintViolated(o, "The 'objectref' must refer to an object that's not an array. Found instead: '"+t+"'."); 1328 } 1329 final ObjectType objreftype = (ObjectType) t; 1330 if (! ( objreftype.equals(curr) || 1331 objreftype.subclassOf(curr) ) ) { 1332 //TODO: One day move to Staerk-et-al's "Set of object types" instead of "wider" object types 1333 // created during the verification. 1334 // "Wider" object types don't allow us to check for things like that below. 1335 //constraintViolated(o, "The referenced field has the ACC_PROTECTED modifier, "+ 1336 // "and it's a member of the current class or a superclass of the current class."+ 1337 // " However, the referenced object type '"+stack().peek()+ 1338 // "' is not the current class or a subclass of the current class."); 1339 } 1340 } 1341 } 1342 1343 // TODO: Could go into Pass 3a. 1344 if (f.isStatic()) { 1345 constraintViolated(o, "Referenced field '"+f+"' is static which it shouldn't be."); 1346 } 1347 1348 } catch (final ClassNotFoundException e) { 1349 // FIXME: maybe not the best way to handle this 1350 throw new AssertionViolatedException("Missing class: " + e, e); 1351 } 1352 } 1353 1354 /** 1355 * Ensures the specific preconditions of the said instruction. 1356 */ 1357 @Override visitGETSTATIC(final GETSTATIC o)1358 public void visitGETSTATIC(final GETSTATIC o) { 1359 // Field must be static: see Pass 3a. 1360 } 1361 1362 /** 1363 * Ensures the specific preconditions of the said instruction. 1364 */ 1365 @Override visitGOTO(final GOTO o)1366 public void visitGOTO(final GOTO o) { 1367 // nothing to do here. 1368 } 1369 1370 /** 1371 * Ensures the specific preconditions of the said instruction. 1372 */ 1373 @Override visitGOTO_W(final GOTO_W o)1374 public void visitGOTO_W(final GOTO_W o) { 1375 // nothing to do here. 1376 } 1377 1378 /** 1379 * Ensures the specific preconditions of the said instruction. 1380 */ 1381 @Override visitI2B(final I2B o)1382 public void visitI2B(final I2B o) { 1383 if (stack().peek() != Type.INT) { 1384 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 1385 } 1386 } 1387 1388 /** 1389 * Ensures the specific preconditions of the said instruction. 1390 */ 1391 @Override visitI2C(final I2C o)1392 public void visitI2C(final I2C o) { 1393 if (stack().peek() != Type.INT) { 1394 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 1395 } 1396 } 1397 1398 /** 1399 * Ensures the specific preconditions of the said instruction. 1400 */ 1401 @Override visitI2D(final I2D o)1402 public void visitI2D(final I2D o) { 1403 if (stack().peek() != Type.INT) { 1404 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 1405 } 1406 } 1407 1408 /** 1409 * Ensures the specific preconditions of the said instruction. 1410 */ 1411 @Override visitI2F(final I2F o)1412 public void visitI2F(final I2F o) { 1413 if (stack().peek() != Type.INT) { 1414 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 1415 } 1416 } 1417 1418 /** 1419 * Ensures the specific preconditions of the said instruction. 1420 */ 1421 @Override visitI2L(final I2L o)1422 public void visitI2L(final I2L o) { 1423 if (stack().peek() != Type.INT) { 1424 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 1425 } 1426 } 1427 1428 /** 1429 * Ensures the specific preconditions of the said instruction. 1430 */ 1431 @Override visitI2S(final I2S o)1432 public void visitI2S(final I2S o) { 1433 if (stack().peek() != Type.INT) { 1434 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 1435 } 1436 } 1437 1438 /** 1439 * Ensures the specific preconditions of the said instruction. 1440 */ 1441 @Override visitIADD(final IADD o)1442 public void visitIADD(final IADD o) { 1443 if (stack().peek() != Type.INT) { 1444 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 1445 } 1446 if (stack().peek(1) != Type.INT) { 1447 constraintViolated(o, "The value at the stack next-to-top is not of type 'int', but of type '"+stack().peek(1)+"'."); 1448 } 1449 } 1450 1451 /** 1452 * Ensures the specific preconditions of the said instruction. 1453 */ 1454 @Override visitIALOAD(final IALOAD o)1455 public void visitIALOAD(final IALOAD o) { 1456 indexOfInt(o, stack().peek()); 1457 if (stack().peek(1) == Type.NULL) { 1458 return; 1459 } 1460 if (! (stack().peek(1) instanceof ArrayType)) { 1461 constraintViolated(o, "Stack next-to-top must be of type int[] but is '"+stack().peek(1)+"'."); 1462 } 1463 final Type t = ((ArrayType) (stack().peek(1))).getBasicType(); 1464 if (t != Type.INT) { 1465 constraintViolated(o, "Stack next-to-top must be of type int[] but is '"+stack().peek(1)+"'."); 1466 } 1467 } 1468 1469 /** 1470 * Ensures the specific preconditions of the said instruction. 1471 */ 1472 @Override visitIAND(final IAND o)1473 public void visitIAND(final IAND o) { 1474 if (stack().peek() != Type.INT) { 1475 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 1476 } 1477 if (stack().peek(1) != Type.INT) { 1478 constraintViolated(o, "The value at the stack next-to-top is not of type 'int', but of type '"+stack().peek(1)+"'."); 1479 } 1480 } 1481 1482 /** 1483 * Ensures the specific preconditions of the said instruction. 1484 */ 1485 @Override visitIASTORE(final IASTORE o)1486 public void visitIASTORE(final IASTORE o) { 1487 if (stack().peek() != Type.INT) { 1488 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 1489 } 1490 indexOfInt(o, stack().peek(1)); 1491 if (stack().peek(2) == Type.NULL) { 1492 return; 1493 } 1494 if (! (stack().peek(2) instanceof ArrayType)) { 1495 constraintViolated(o, "Stack next-to-next-to-top must be of type int[] but is '"+stack().peek(2)+"'."); 1496 } 1497 final Type t = ((ArrayType) (stack().peek(2))).getBasicType(); 1498 if (t != Type.INT) { 1499 constraintViolated(o, "Stack next-to-next-to-top must be of type int[] but is '"+stack().peek(2)+"'."); 1500 } 1501 } 1502 1503 /** 1504 * Ensures the specific preconditions of the said instruction. 1505 */ 1506 @Override visitICONST(final ICONST o)1507 public void visitICONST(final ICONST o) { 1508 //nothing to do here. 1509 } 1510 1511 /** 1512 * Ensures the specific preconditions of the said instruction. 1513 */ 1514 @Override visitIDIV(final IDIV o)1515 public void visitIDIV(final IDIV o) { 1516 if (stack().peek() != Type.INT) { 1517 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 1518 } 1519 if (stack().peek(1) != Type.INT) { 1520 constraintViolated(o, "The value at the stack next-to-top is not of type 'int', but of type '"+stack().peek(1)+"'."); 1521 } 1522 } 1523 1524 /** 1525 * Ensures the specific preconditions of the said instruction. 1526 */ 1527 @Override visitIF_ACMPEQ(final IF_ACMPEQ o)1528 public void visitIF_ACMPEQ(final IF_ACMPEQ o) { 1529 if (!(stack().peek() instanceof ReferenceType)) { 1530 constraintViolated(o, "The value at the stack top is not of a ReferenceType, but of type '"+stack().peek()+"'."); 1531 } 1532 //referenceTypeIsInitialized(o, (ReferenceType) (stack().peek()) ); 1533 1534 if (!(stack().peek(1) instanceof ReferenceType)) { 1535 constraintViolated(o, "The value at the stack next-to-top is not of a ReferenceType, but of type '"+stack().peek(1)+"'."); 1536 } 1537 //referenceTypeIsInitialized(o, (ReferenceType) (stack().peek(1)) ); 1538 1539 } 1540 1541 /** 1542 * Ensures the specific preconditions of the said instruction. 1543 */ 1544 @Override visitIF_ACMPNE(final IF_ACMPNE o)1545 public void visitIF_ACMPNE(final IF_ACMPNE o) { 1546 if (!(stack().peek() instanceof ReferenceType)) { 1547 constraintViolated(o, "The value at the stack top is not of a ReferenceType, but of type '"+stack().peek()+"'."); 1548 //referenceTypeIsInitialized(o, (ReferenceType) (stack().peek()) ); 1549 } 1550 if (!(stack().peek(1) instanceof ReferenceType)) { 1551 constraintViolated(o, "The value at the stack next-to-top is not of a ReferenceType, but of type '"+stack().peek(1)+"'."); 1552 //referenceTypeIsInitialized(o, (ReferenceType) (stack().peek(1)) ); 1553 } 1554 } 1555 1556 /** 1557 * Ensures the specific preconditions of the said instruction. 1558 */ 1559 @Override visitIF_ICMPEQ(final IF_ICMPEQ o)1560 public void visitIF_ICMPEQ(final IF_ICMPEQ o) { 1561 if (stack().peek() != Type.INT) { 1562 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 1563 } 1564 if (stack().peek(1) != Type.INT) { 1565 constraintViolated(o, "The value at the stack next-to-top is not of type 'int', but of type '"+stack().peek(1)+"'."); 1566 } 1567 } 1568 1569 /** 1570 * Ensures the specific preconditions of the said instruction. 1571 */ 1572 @Override visitIF_ICMPGE(final IF_ICMPGE o)1573 public void visitIF_ICMPGE(final IF_ICMPGE o) { 1574 if (stack().peek() != Type.INT) { 1575 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 1576 } 1577 if (stack().peek(1) != Type.INT) { 1578 constraintViolated(o, "The value at the stack next-to-top is not of type 'int', but of type '"+stack().peek(1)+"'."); 1579 } 1580 } 1581 1582 /** 1583 * Ensures the specific preconditions of the said instruction. 1584 */ 1585 @Override visitIF_ICMPGT(final IF_ICMPGT o)1586 public void visitIF_ICMPGT(final IF_ICMPGT o) { 1587 if (stack().peek() != Type.INT) { 1588 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 1589 } 1590 if (stack().peek(1) != Type.INT) { 1591 constraintViolated(o, "The value at the stack next-to-top is not of type 'int', but of type '"+stack().peek(1)+"'."); 1592 } 1593 } 1594 1595 /** 1596 * Ensures the specific preconditions of the said instruction. 1597 */ 1598 @Override visitIF_ICMPLE(final IF_ICMPLE o)1599 public void visitIF_ICMPLE(final IF_ICMPLE o) { 1600 if (stack().peek() != Type.INT) { 1601 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 1602 } 1603 if (stack().peek(1) != Type.INT) { 1604 constraintViolated(o, "The value at the stack next-to-top is not of type 'int', but of type '"+stack().peek(1)+"'."); 1605 } 1606 } 1607 1608 /** 1609 * Ensures the specific preconditions of the said instruction. 1610 */ 1611 @Override visitIF_ICMPLT(final IF_ICMPLT o)1612 public void visitIF_ICMPLT(final IF_ICMPLT o) { 1613 if (stack().peek() != Type.INT) { 1614 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 1615 } 1616 if (stack().peek(1) != Type.INT) { 1617 constraintViolated(o, "The value at the stack next-to-top is not of type 'int', but of type '"+stack().peek(1)+"'."); 1618 } 1619 } 1620 1621 /** 1622 * Ensures the specific preconditions of the said instruction. 1623 */ 1624 @Override visitIF_ICMPNE(final IF_ICMPNE o)1625 public void visitIF_ICMPNE(final IF_ICMPNE o) { 1626 if (stack().peek() != Type.INT) { 1627 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 1628 } 1629 if (stack().peek(1) != Type.INT) { 1630 constraintViolated(o, "The value at the stack next-to-top is not of type 'int', but of type '"+stack().peek(1)+"'."); 1631 } 1632 } 1633 1634 /** 1635 * Ensures the specific preconditions of the said instruction. 1636 */ 1637 @Override visitIFEQ(final IFEQ o)1638 public void visitIFEQ(final IFEQ o) { 1639 if (stack().peek() != Type.INT) { 1640 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 1641 } 1642 } 1643 1644 /** 1645 * Ensures the specific preconditions of the said instruction. 1646 */ 1647 @Override visitIFGE(final IFGE o)1648 public void visitIFGE(final IFGE o) { 1649 if (stack().peek() != Type.INT) { 1650 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 1651 } 1652 } 1653 1654 /** 1655 * Ensures the specific preconditions of the said instruction. 1656 */ 1657 @Override visitIFGT(final IFGT o)1658 public void visitIFGT(final IFGT o) { 1659 if (stack().peek() != Type.INT) { 1660 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 1661 } 1662 } 1663 1664 /** 1665 * Ensures the specific preconditions of the said instruction. 1666 */ 1667 @Override visitIFLE(final IFLE o)1668 public void visitIFLE(final IFLE o) { 1669 if (stack().peek() != Type.INT) { 1670 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 1671 } 1672 } 1673 1674 /** 1675 * Ensures the specific preconditions of the said instruction. 1676 */ 1677 @Override visitIFLT(final IFLT o)1678 public void visitIFLT(final IFLT o) { 1679 if (stack().peek() != Type.INT) { 1680 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 1681 } 1682 } 1683 1684 /** 1685 * Ensures the specific preconditions of the said instruction. 1686 */ 1687 @Override visitIFNE(final IFNE o)1688 public void visitIFNE(final IFNE o) { 1689 if (stack().peek() != Type.INT) { 1690 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 1691 } 1692 } 1693 1694 /** 1695 * Ensures the specific preconditions of the said instruction. 1696 */ 1697 @Override visitIFNONNULL(final IFNONNULL o)1698 public void visitIFNONNULL(final IFNONNULL o) { 1699 if (!(stack().peek() instanceof ReferenceType)) { 1700 constraintViolated(o, "The value at the stack top is not of a ReferenceType, but of type '"+stack().peek()+"'."); 1701 } 1702 referenceTypeIsInitialized(o, (ReferenceType) (stack().peek()) ); 1703 } 1704 1705 /** 1706 * Ensures the specific preconditions of the said instruction. 1707 */ 1708 @Override visitIFNULL(final IFNULL o)1709 public void visitIFNULL(final IFNULL o) { 1710 if (!(stack().peek() instanceof ReferenceType)) { 1711 constraintViolated(o, "The value at the stack top is not of a ReferenceType, but of type '"+stack().peek()+"'."); 1712 } 1713 referenceTypeIsInitialized(o, (ReferenceType) (stack().peek()) ); 1714 } 1715 1716 /** 1717 * Ensures the specific preconditions of the said instruction. 1718 */ 1719 @Override visitIINC(final IINC o)1720 public void visitIINC(final IINC o) { 1721 // Mhhh. In BCEL, at this time "IINC" is not a LocalVariableInstruction. 1722 if (locals().maxLocals() <= (o.getType(cpg).getSize()==1? o.getIndex() : o.getIndex()+1) ) { 1723 constraintViolated(o, "The 'index' is not a valid index into the local variable array."); 1724 } 1725 1726 indexOfInt(o, locals().get(o.getIndex())); 1727 } 1728 1729 /** 1730 * Ensures the specific preconditions of the said instruction. 1731 */ 1732 @Override visitILOAD(final ILOAD o)1733 public void visitILOAD(final ILOAD o) { 1734 // All done by visitLocalVariableInstruction(), visitLoadInstruction() 1735 } 1736 1737 /** 1738 * Ensures the specific preconditions of the said instruction. 1739 */ 1740 @Override visitIMPDEP1(final IMPDEP1 o)1741 public void visitIMPDEP1(final IMPDEP1 o) { 1742 throw new AssertionViolatedException( 1743 "In this JustIce verification pass there should not occur an illegal instruction such as IMPDEP1."); 1744 } 1745 1746 /** 1747 * Ensures the specific preconditions of the said instruction. 1748 */ 1749 @Override visitIMPDEP2(final IMPDEP2 o)1750 public void visitIMPDEP2(final IMPDEP2 o) { 1751 throw new AssertionViolatedException( 1752 "In this JustIce verification pass there should not occur an illegal instruction such as IMPDEP2."); 1753 } 1754 1755 /** 1756 * Ensures the specific preconditions of the said instruction. 1757 */ 1758 @Override visitIMUL(final IMUL o)1759 public void visitIMUL(final IMUL o) { 1760 if (stack().peek() != Type.INT) { 1761 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 1762 } 1763 if (stack().peek(1) != Type.INT) { 1764 constraintViolated(o, "The value at the stack next-to-top is not of type 'int', but of type '"+stack().peek(1)+"'."); 1765 } 1766 } 1767 1768 /** 1769 * Ensures the specific preconditions of the said instruction. 1770 */ 1771 @Override visitINEG(final INEG o)1772 public void visitINEG(final INEG o) { 1773 if (stack().peek() != Type.INT) { 1774 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 1775 } 1776 } 1777 1778 /** 1779 * Ensures the specific preconditions of the said instruction. 1780 */ 1781 @Override visitINSTANCEOF(final INSTANCEOF o)1782 public void visitINSTANCEOF(final INSTANCEOF o) { 1783 // The objectref must be of type reference. 1784 final Type objectref = stack().peek(0); 1785 if (!(objectref instanceof ReferenceType)) { 1786 constraintViolated(o, "The 'objectref' is not of a ReferenceType but of type "+objectref+"."); 1787 } 1788 //else{ 1789 // referenceTypeIsInitialized(o, (ReferenceType) objectref); 1790 //} 1791 // The unsigned indexbyte1 and indexbyte2 are used to construct an index into the runtime constant pool of the 1792 // current class (�3.6), where the value of the index is (indexbyte1 << 8) | indexbyte2. The runtime constant 1793 // pool item at the index must be a symbolic reference to a class, array, or interface type. 1794 final Constant c = cpg.getConstant(o.getIndex()); 1795 if (! (c instanceof ConstantClass)) { 1796 constraintViolated(o, "The Constant at 'index' is not a ConstantClass, but '"+c+"'."); 1797 } 1798 } 1799 1800 /** 1801 * Ensures the specific preconditions of the said instruction. 1802 * @since 6.0 1803 */ 1804 @Override visitINVOKEDYNAMIC(final INVOKEDYNAMIC o)1805 public void visitINVOKEDYNAMIC(final INVOKEDYNAMIC o) { 1806 throw new RuntimeException("INVOKEDYNAMIC instruction is not supported at this time"); 1807 } 1808 1809 /** 1810 * Ensures the specific preconditions of the said instruction. 1811 */ 1812 @Override visitINVOKEINTERFACE(final INVOKEINTERFACE o)1813 public void visitINVOKEINTERFACE(final INVOKEINTERFACE o) { 1814 // Method is not native, otherwise pass 3 would not happen. 1815 1816 final int count = o.getCount(); 1817 if (count == 0) { 1818 constraintViolated(o, "The 'count' argument must not be 0."); 1819 } 1820 // It is a ConstantInterfaceMethodref, Pass 3a made it sure. 1821 // TODO: Do we want to do anything with it? 1822 //ConstantInterfaceMethodref cimr = (ConstantInterfaceMethodref) (cpg.getConstant(o.getIndex())); 1823 1824 // the o.getClassType(cpg) type has passed pass 2; see visitLoadClass(o). 1825 1826 final Type t = o.getType(cpg); 1827 if (t instanceof ObjectType) { 1828 final String name = ((ObjectType)t).getClassName(); 1829 final Verifier v = VerifierFactory.getVerifier( name ); 1830 final VerificationResult vr = v.doPass2(); 1831 if (vr.getStatus() != VerificationResult.VERIFIED_OK) { 1832 constraintViolated(o, "Class '"+name+"' is referenced, but cannot be loaded and resolved: '"+vr+"'."); 1833 } 1834 } 1835 1836 1837 final Type[] argtypes = o.getArgumentTypes(cpg); 1838 final int nargs = argtypes.length; 1839 1840 for (int i=nargs-1; i>=0; i--) { 1841 final Type fromStack = stack().peek( (nargs-1) - i ); // 0 to nargs-1 1842 Type fromDesc = argtypes[i]; 1843 if (fromDesc == Type.BOOLEAN || 1844 fromDesc == Type.BYTE || 1845 fromDesc == Type.CHAR || 1846 fromDesc == Type.SHORT) { 1847 fromDesc = Type.INT; 1848 } 1849 if (! fromStack.equals(fromDesc)) { 1850 if (fromStack instanceof ReferenceType && fromDesc instanceof ReferenceType) { 1851 final ReferenceType rFromStack = (ReferenceType) fromStack; 1852 //ReferenceType rFromDesc = (ReferenceType) fromDesc; 1853 // TODO: This can only be checked when using Staerk-et-al's "set of object types" 1854 // instead of a "wider cast object type" created during verification. 1855 //if ( ! rFromStack.isAssignmentCompatibleWith(rFromDesc) ) { 1856 // constraintViolated(o, "Expecting a '"+fromDesc+"' but found a '"+fromStack+ 1857 // "' on the stack (which is not assignment compatible)."); 1858 //} 1859 referenceTypeIsInitialized(o, rFromStack); 1860 } 1861 else{ 1862 constraintViolated(o, "Expecting a '"+fromDesc+"' but found a '"+fromStack+"' on the stack."); 1863 } 1864 } 1865 } 1866 1867 Type objref = stack().peek(nargs); 1868 if (objref == Type.NULL) { 1869 return; 1870 } 1871 if (! (objref instanceof ReferenceType) ) { 1872 constraintViolated(o, "Expecting a reference type as 'objectref' on the stack, not a '"+objref+"'."); 1873 } 1874 referenceTypeIsInitialized(o, (ReferenceType) objref); 1875 if (!(objref instanceof ObjectType)) { 1876 if (!(objref instanceof ArrayType)) { // could be a ReturnaddressType 1877 constraintViolated(o, "Expecting an ObjectType as 'objectref' on the stack, not a '"+objref+"'."); 1878 } 1879 else{ 1880 objref = GENERIC_ARRAY; 1881 } 1882 } 1883 1884 // String objref_classname = ((ObjectType) objref).getClassName(); 1885 // String theInterface = o.getClassName(cpg); 1886 // TODO: This can only be checked if we're using Staerk-et-al's "set of object types" 1887 // instead of "wider cast object types" generated during verification. 1888 //if ( ! Repository.implementationOf(objref_classname, theInterface) ) { 1889 // constraintViolated(o, "The 'objref' item '"+objref+"' does not implement '"+theInterface+"' as expected."); 1890 //} 1891 1892 int counted_count = 1; // 1 for the objectref 1893 for (int i=0; i<nargs; i++) { 1894 counted_count += argtypes[i].getSize(); 1895 } 1896 if (count != counted_count) { 1897 constraintViolated(o, "The 'count' argument should probably read '"+counted_count+"' but is '"+count+"'."); 1898 } 1899 } 1900 1901 /** 1902 * Ensures the specific preconditions of the said instruction. 1903 */ 1904 @Override visitINVOKESPECIAL(final INVOKESPECIAL o)1905 public void visitINVOKESPECIAL(final INVOKESPECIAL o) { 1906 try { 1907 // Don't init an object twice. 1908 if ( (o.getMethodName(cpg).equals(Const.CONSTRUCTOR_NAME)) && 1909 (!(stack().peek(o.getArgumentTypes(cpg).length) instanceof UninitializedObjectType)) ) { 1910 constraintViolated(o, "Possibly initializing object twice."+ 1911 " A valid instruction sequence must not have an uninitialized object on the operand stack or in a local variable"+ 1912 " during a backwards branch, or in a local variable in code protected by an exception handler."+ 1913 " Please see The Java Virtual Machine Specification, Second Edition, 4.9.4 (pages 147 and 148) for details."); 1914 } 1915 1916 // the o.getClassType(cpg) type has passed pass 2; see visitLoadClass(o). 1917 1918 final Type t = o.getType(cpg); 1919 if (t instanceof ObjectType) { 1920 final String name = ((ObjectType)t).getClassName(); 1921 final Verifier v = VerifierFactory.getVerifier( name ); 1922 final VerificationResult vr = v.doPass2(); 1923 if (vr.getStatus() != VerificationResult.VERIFIED_OK) { 1924 constraintViolated(o, "Class '"+name+"' is referenced, but cannot be loaded and resolved: '"+vr+"'."); 1925 } 1926 } 1927 1928 1929 final Type[] argtypes = o.getArgumentTypes(cpg); 1930 final int nargs = argtypes.length; 1931 1932 for (int i=nargs-1; i>=0; i--) { 1933 final Type fromStack = stack().peek( (nargs-1) - i ); // 0 to nargs-1 1934 Type fromDesc = argtypes[i]; 1935 if (fromDesc == Type.BOOLEAN || 1936 fromDesc == Type.BYTE || 1937 fromDesc == Type.CHAR || 1938 fromDesc == Type.SHORT) { 1939 fromDesc = Type.INT; 1940 } 1941 if (! fromStack.equals(fromDesc)) { 1942 if (fromStack instanceof ReferenceType && fromDesc instanceof ReferenceType) { 1943 final ReferenceType rFromStack = (ReferenceType) fromStack; 1944 final ReferenceType rFromDesc = (ReferenceType) fromDesc; 1945 // TODO: This can only be checked using Staerk-et-al's "set of object types", not 1946 // using a "wider cast object type". 1947 if ( ! rFromStack.isAssignmentCompatibleWith(rFromDesc) ) { 1948 constraintViolated(o, "Expecting a '"+fromDesc+"' but found a '"+fromStack+ 1949 "' on the stack (which is not assignment compatible)."); 1950 } 1951 referenceTypeIsInitialized(o, rFromStack); 1952 } 1953 else{ 1954 constraintViolated(o, "Expecting a '"+fromDesc+"' but found a '"+fromStack+"' on the stack."); 1955 } 1956 } 1957 } 1958 1959 Type objref = stack().peek(nargs); 1960 if (objref == Type.NULL) { 1961 return; 1962 } 1963 if (! (objref instanceof ReferenceType) ) { 1964 constraintViolated(o, "Expecting a reference type as 'objectref' on the stack, not a '"+objref+"'."); 1965 } 1966 String objref_classname = null; 1967 if ( !(o.getMethodName(cpg).equals(Const.CONSTRUCTOR_NAME))) { 1968 referenceTypeIsInitialized(o, (ReferenceType) objref); 1969 if (!(objref instanceof ObjectType)) { 1970 if (!(objref instanceof ArrayType)) { // could be a ReturnaddressType 1971 constraintViolated(o, "Expecting an ObjectType as 'objectref' on the stack, not a '"+objref+"'."); 1972 } 1973 else{ 1974 objref = GENERIC_ARRAY; 1975 } 1976 } 1977 1978 objref_classname = ((ObjectType) objref).getClassName(); 1979 } 1980 else{ 1981 if (!(objref instanceof UninitializedObjectType)) { 1982 constraintViolated(o, "Expecting an UninitializedObjectType as 'objectref' on the stack, not a '"+objref+ 1983 "'. Otherwise, you couldn't invoke a method since an array has no methods (not to speak of a return address)."); 1984 } 1985 objref_classname = ((UninitializedObjectType) objref).getInitialized().getClassName(); 1986 } 1987 1988 1989 final String theClass = o.getClassName(cpg); 1990 if ( ! Repository.instanceOf(objref_classname, theClass) ) { 1991 constraintViolated(o, "The 'objref' item '"+objref+"' does not implement '"+theClass+"' as expected."); 1992 } 1993 1994 } catch (final ClassNotFoundException e) { 1995 // FIXME: maybe not the best way to handle this 1996 throw new AssertionViolatedException("Missing class: " + e, e); 1997 } 1998 } 1999 2000 /** 2001 * Ensures the specific preconditions of the said instruction. 2002 */ 2003 @Override visitINVOKESTATIC(final INVOKESTATIC o)2004 public void visitINVOKESTATIC(final INVOKESTATIC o) { 2005 try { 2006 // Method is not native, otherwise pass 3 would not happen. 2007 2008 final Type t = o.getType(cpg); 2009 if (t instanceof ObjectType) { 2010 final String name = ((ObjectType)t).getClassName(); 2011 final Verifier v = VerifierFactory.getVerifier( name ); 2012 final VerificationResult vr = v.doPass2(); 2013 if (vr.getStatus() != VerificationResult.VERIFIED_OK) { 2014 constraintViolated(o, "Class '"+name+"' is referenced, but cannot be loaded and resolved: '"+vr+"'."); 2015 } 2016 } 2017 2018 final Type[] argtypes = o.getArgumentTypes(cpg); 2019 final int nargs = argtypes.length; 2020 2021 for (int i=nargs-1; i>=0; i--) { 2022 final Type fromStack = stack().peek( (nargs-1) - i ); // 0 to nargs-1 2023 Type fromDesc = argtypes[i]; 2024 if (fromDesc == Type.BOOLEAN || 2025 fromDesc == Type.BYTE || 2026 fromDesc == Type.CHAR || 2027 fromDesc == Type.SHORT) { 2028 fromDesc = Type.INT; 2029 } 2030 if (! fromStack.equals(fromDesc)) { 2031 if (fromStack instanceof ReferenceType && fromDesc instanceof ReferenceType) { 2032 final ReferenceType rFromStack = (ReferenceType) fromStack; 2033 final ReferenceType rFromDesc = (ReferenceType) fromDesc; 2034 // TODO: This check can possibly only be done using Staerk-et-al's "set of object types" 2035 // instead of a "wider cast object type" created during verification. 2036 if ( ! rFromStack.isAssignmentCompatibleWith(rFromDesc) ) { 2037 constraintViolated(o, "Expecting a '"+fromDesc+"' but found a '"+fromStack+ 2038 "' on the stack (which is not assignment compatible)."); 2039 } 2040 referenceTypeIsInitialized(o, rFromStack); 2041 } 2042 else{ 2043 constraintViolated(o, "Expecting a '"+fromDesc+"' but found a '"+fromStack+"' on the stack."); 2044 } 2045 } 2046 } 2047 } catch (final ClassNotFoundException e) { 2048 // FIXME: maybe not the best way to handle this 2049 throw new AssertionViolatedException("Missing class: " + e, e); 2050 } 2051 } 2052 2053 /** 2054 * Ensures the specific preconditions of the said instruction. 2055 */ 2056 @Override visitINVOKEVIRTUAL(final INVOKEVIRTUAL o)2057 public void visitINVOKEVIRTUAL(final INVOKEVIRTUAL o) { 2058 try { 2059 // the o.getClassType(cpg) type has passed pass 2; see visitLoadClass(o). 2060 2061 final Type t = o.getType(cpg); 2062 if (t instanceof ObjectType) { 2063 final String name = ((ObjectType)t).getClassName(); 2064 final Verifier v = VerifierFactory.getVerifier( name ); 2065 final VerificationResult vr = v.doPass2(); 2066 if (vr.getStatus() != VerificationResult.VERIFIED_OK) { 2067 constraintViolated(o, "Class '"+name+"' is referenced, but cannot be loaded and resolved: '"+vr+"'."); 2068 } 2069 } 2070 2071 2072 final Type[] argtypes = o.getArgumentTypes(cpg); 2073 final int nargs = argtypes.length; 2074 2075 for (int i=nargs-1; i>=0; i--) { 2076 final Type fromStack = stack().peek( (nargs-1) - i ); // 0 to nargs-1 2077 Type fromDesc = argtypes[i]; 2078 if (fromDesc == Type.BOOLEAN || 2079 fromDesc == Type.BYTE || 2080 fromDesc == Type.CHAR || 2081 fromDesc == Type.SHORT) { 2082 fromDesc = Type.INT; 2083 } 2084 if (! fromStack.equals(fromDesc)) { 2085 if (fromStack instanceof ReferenceType && fromDesc instanceof ReferenceType) { 2086 final ReferenceType rFromStack = (ReferenceType) fromStack; 2087 final ReferenceType rFromDesc = (ReferenceType) fromDesc; 2088 // TODO: This can possibly only be checked when using Staerk-et-al's "set of object types" instead 2089 // of a single "wider cast object type" created during verification. 2090 if ( ! rFromStack.isAssignmentCompatibleWith(rFromDesc) ) { 2091 constraintViolated(o, "Expecting a '"+fromDesc+"' but found a '"+fromStack+ 2092 "' on the stack (which is not assignment compatible)."); 2093 } 2094 referenceTypeIsInitialized(o, rFromStack); 2095 } 2096 else{ 2097 constraintViolated(o, "Expecting a '"+fromDesc+"' but found a '"+fromStack+"' on the stack."); 2098 } 2099 } 2100 } 2101 2102 Type objref = stack().peek(nargs); 2103 if (objref == Type.NULL) { 2104 return; 2105 } 2106 if (! (objref instanceof ReferenceType) ) { 2107 constraintViolated(o, "Expecting a reference type as 'objectref' on the stack, not a '"+objref+"'."); 2108 } 2109 referenceTypeIsInitialized(o, (ReferenceType) objref); 2110 if (!(objref instanceof ObjectType)) { 2111 if (!(objref instanceof ArrayType)) { // could be a ReturnaddressType 2112 constraintViolated(o, "Expecting an ObjectType as 'objectref' on the stack, not a '"+objref+"'."); 2113 } 2114 else{ 2115 objref = GENERIC_ARRAY; 2116 } 2117 } 2118 2119 final String objref_classname = ((ObjectType) objref).getClassName(); 2120 2121 final String theClass = o.getClassName(cpg); 2122 2123 if ( ! Repository.instanceOf(objref_classname, theClass) ) { 2124 constraintViolated(o, "The 'objref' item '"+objref+"' does not implement '"+theClass+"' as expected."); 2125 } 2126 } catch (final ClassNotFoundException e) { 2127 // FIXME: maybe not the best way to handle this 2128 throw new AssertionViolatedException("Missing class: " + e, e); 2129 } 2130 } 2131 2132 /** 2133 * Ensures the specific preconditions of the said instruction. 2134 */ 2135 @Override visitIOR(final IOR o)2136 public void visitIOR(final IOR o) { 2137 if (stack().peek() != Type.INT) { 2138 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 2139 } 2140 if (stack().peek(1) != Type.INT) { 2141 constraintViolated(o, "The value at the stack next-to-top is not of type 'int', but of type '"+stack().peek(1)+"'."); 2142 } 2143 } 2144 2145 /** 2146 * Ensures the specific preconditions of the said instruction. 2147 */ 2148 @Override visitIREM(final IREM o)2149 public void visitIREM(final IREM o) { 2150 if (stack().peek() != Type.INT) { 2151 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 2152 } 2153 if (stack().peek(1) != Type.INT) { 2154 constraintViolated(o, "The value at the stack next-to-top is not of type 'int', but of type '"+stack().peek(1)+"'."); 2155 } 2156 } 2157 2158 /** 2159 * Ensures the specific preconditions of the said instruction. 2160 */ 2161 @Override visitIRETURN(final IRETURN o)2162 public void visitIRETURN(final IRETURN o) { 2163 if (stack().peek() != Type.INT) { 2164 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 2165 } 2166 } 2167 2168 /** 2169 * Ensures the specific preconditions of the said instruction. 2170 */ 2171 @Override visitISHL(final ISHL o)2172 public void visitISHL(final ISHL o) { 2173 if (stack().peek() != Type.INT) { 2174 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 2175 } 2176 if (stack().peek(1) != Type.INT) { 2177 constraintViolated(o, "The value at the stack next-to-top is not of type 'int', but of type '"+stack().peek(1)+"'."); 2178 } 2179 } 2180 2181 /** 2182 * Ensures the specific preconditions of the said instruction. 2183 */ 2184 @Override visitISHR(final ISHR o)2185 public void visitISHR(final ISHR o) { 2186 if (stack().peek() != Type.INT) { 2187 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 2188 } 2189 if (stack().peek(1) != Type.INT) { 2190 constraintViolated(o, "The value at the stack next-to-top is not of type 'int', but of type '"+stack().peek(1)+"'."); 2191 } 2192 } 2193 2194 /** 2195 * Ensures the specific preconditions of the said instruction. 2196 */ 2197 @Override visitISTORE(final ISTORE o)2198 public void visitISTORE(final ISTORE o) { 2199 //visitStoreInstruction(StoreInstruction) is called before. 2200 2201 // Nothing else needs to be done here. 2202 } 2203 2204 /** 2205 * Ensures the specific preconditions of the said instruction. 2206 */ 2207 @Override visitISUB(final ISUB o)2208 public void visitISUB(final ISUB o) { 2209 if (stack().peek() != Type.INT) { 2210 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 2211 } 2212 if (stack().peek(1) != Type.INT) { 2213 constraintViolated(o, "The value at the stack next-to-top is not of type 'int', but of type '"+stack().peek(1)+"'."); 2214 } 2215 } 2216 2217 /** 2218 * Ensures the specific preconditions of the said instruction. 2219 */ 2220 @Override visitIUSHR(final IUSHR o)2221 public void visitIUSHR(final IUSHR o) { 2222 if (stack().peek() != Type.INT) { 2223 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 2224 } 2225 if (stack().peek(1) != Type.INT) { 2226 constraintViolated(o, "The value at the stack next-to-top is not of type 'int', but of type '"+stack().peek(1)+"'."); 2227 } 2228 } 2229 2230 /** 2231 * Ensures the specific preconditions of the said instruction. 2232 */ 2233 @Override visitIXOR(final IXOR o)2234 public void visitIXOR(final IXOR o) { 2235 if (stack().peek() != Type.INT) { 2236 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 2237 } 2238 if (stack().peek(1) != Type.INT) { 2239 constraintViolated(o, "The value at the stack next-to-top is not of type 'int', but of type '"+stack().peek(1)+"'."); 2240 } 2241 } 2242 2243 /** 2244 * Ensures the specific preconditions of the said instruction. 2245 */ 2246 @Override visitJSR(final JSR o)2247 public void visitJSR(final JSR o) { 2248 // nothing to do here. 2249 } 2250 2251 /** 2252 * Ensures the specific preconditions of the said instruction. 2253 */ 2254 @Override visitJSR_W(final JSR_W o)2255 public void visitJSR_W(final JSR_W o) { 2256 // nothing to do here. 2257 } 2258 2259 /** 2260 * Ensures the specific preconditions of the said instruction. 2261 */ 2262 @Override visitL2D(final L2D o)2263 public void visitL2D(final L2D o) { 2264 if (stack().peek() != Type.LONG) { 2265 constraintViolated(o, "The value at the stack top is not of type 'long', but of type '"+stack().peek()+"'."); 2266 } 2267 } 2268 2269 /** 2270 * Ensures the specific preconditions of the said instruction. 2271 */ 2272 @Override visitL2F(final L2F o)2273 public void visitL2F(final L2F o) { 2274 if (stack().peek() != Type.LONG) { 2275 constraintViolated(o, "The value at the stack top is not of type 'long', but of type '"+stack().peek()+"'."); 2276 } 2277 } 2278 2279 /** 2280 * Ensures the specific preconditions of the said instruction. 2281 */ 2282 @Override visitL2I(final L2I o)2283 public void visitL2I(final L2I o) { 2284 if (stack().peek() != Type.LONG) { 2285 constraintViolated(o, "The value at the stack top is not of type 'long', but of type '"+stack().peek()+"'."); 2286 } 2287 } 2288 2289 /** 2290 * Ensures the specific preconditions of the said instruction. 2291 */ 2292 @Override visitLADD(final LADD o)2293 public void visitLADD(final LADD o) { 2294 if (stack().peek() != Type.LONG) { 2295 constraintViolated(o, "The value at the stack top is not of type 'long', but of type '"+stack().peek()+"'."); 2296 } 2297 if (stack().peek(1) != Type.LONG) { 2298 constraintViolated(o, "The value at the stack next-to-top is not of type 'long', but of type '"+stack().peek(1)+"'."); 2299 } 2300 } 2301 2302 /** 2303 * Ensures the specific preconditions of the said instruction. 2304 */ 2305 @Override visitLALOAD(final LALOAD o)2306 public void visitLALOAD(final LALOAD o) { 2307 indexOfInt(o, stack().peek()); 2308 if (stack().peek(1) == Type.NULL) { 2309 return; 2310 } 2311 if (! (stack().peek(1) instanceof ArrayType)) { 2312 constraintViolated(o, "Stack next-to-top must be of type long[] but is '"+stack().peek(1)+"'."); 2313 } 2314 final Type t = ((ArrayType) (stack().peek(1))).getBasicType(); 2315 if (t != Type.LONG) { 2316 constraintViolated(o, "Stack next-to-top must be of type long[] but is '"+stack().peek(1)+"'."); 2317 } 2318 } 2319 2320 /** 2321 * Ensures the specific preconditions of the said instruction. 2322 */ 2323 @Override visitLAND(final LAND o)2324 public void visitLAND(final LAND o) { 2325 if (stack().peek() != Type.LONG) { 2326 constraintViolated(o, "The value at the stack top is not of type 'long', but of type '"+stack().peek()+"'."); 2327 } 2328 if (stack().peek(1) != Type.LONG) { 2329 constraintViolated(o, "The value at the stack next-to-top is not of type 'long', but of type '"+stack().peek(1)+"'."); 2330 } 2331 } 2332 2333 /** 2334 * Ensures the specific preconditions of the said instruction. 2335 */ 2336 @Override visitLASTORE(final LASTORE o)2337 public void visitLASTORE(final LASTORE o) { 2338 if (stack().peek() != Type.LONG) { 2339 constraintViolated(o, "The value at the stack top is not of type 'long', but of type '"+stack().peek()+"'."); 2340 } 2341 indexOfInt(o, stack().peek(1)); 2342 if (stack().peek(2) == Type.NULL) { 2343 return; 2344 } 2345 if (! (stack().peek(2) instanceof ArrayType)) { 2346 constraintViolated(o, "Stack next-to-next-to-top must be of type long[] but is '"+stack().peek(2)+"'."); 2347 } 2348 final Type t = ((ArrayType) (stack().peek(2))).getBasicType(); 2349 if (t != Type.LONG) { 2350 constraintViolated(o, "Stack next-to-next-to-top must be of type long[] but is '"+stack().peek(2)+"'."); 2351 } 2352 } 2353 2354 /** 2355 * Ensures the specific preconditions of the said instruction. 2356 */ 2357 @Override visitLCMP(final LCMP o)2358 public void visitLCMP(final LCMP o) { 2359 if (stack().peek() != Type.LONG) { 2360 constraintViolated(o, "The value at the stack top is not of type 'long', but of type '"+stack().peek()+"'."); 2361 } 2362 if (stack().peek(1) != Type.LONG) { 2363 constraintViolated(o, "The value at the stack next-to-top is not of type 'long', but of type '"+stack().peek(1)+"'."); 2364 } 2365 } 2366 2367 /** 2368 * Ensures the specific preconditions of the said instruction. 2369 */ 2370 @Override visitLCONST(final LCONST o)2371 public void visitLCONST(final LCONST o) { 2372 // Nothing to do here. 2373 } 2374 2375 /** 2376 * Ensures the specific preconditions of the said instruction. 2377 */ 2378 @Override visitLDC(final LDC o)2379 public void visitLDC(final LDC o) { 2380 // visitCPInstruction is called first. 2381 2382 final Constant c = cpg.getConstant(o.getIndex()); 2383 if (! ( ( c instanceof ConstantInteger) || 2384 ( c instanceof ConstantFloat ) || 2385 ( c instanceof ConstantString ) || 2386 ( c instanceof ConstantClass ) ) ) { 2387 constraintViolated(o, 2388 "Referenced constant should be a CONSTANT_Integer, a CONSTANT_Float, a CONSTANT_String or a CONSTANT_Class, but is '"+ 2389 c + "'."); 2390 } 2391 } 2392 2393 /** 2394 * Ensures the specific preconditions of the said instruction. 2395 */ visitLDC_W(final LDC_W o)2396 public void visitLDC_W(final LDC_W o) { 2397 // visitCPInstruction is called first. 2398 2399 final Constant c = cpg.getConstant(o.getIndex()); 2400 if (! ( ( c instanceof ConstantInteger) || 2401 ( c instanceof ConstantFloat ) || 2402 ( c instanceof ConstantString ) || 2403 ( c instanceof ConstantClass ) ) ) { 2404 constraintViolated(o, 2405 "Referenced constant should be a CONSTANT_Integer, a CONSTANT_Float, a CONSTANT_String or a CONSTANT_Class, but is '"+ 2406 c + "'."); 2407 } 2408 } 2409 2410 /** 2411 * Ensures the specific preconditions of the said instruction. 2412 */ 2413 @Override visitLDC2_W(final LDC2_W o)2414 public void visitLDC2_W(final LDC2_W o) { 2415 // visitCPInstruction is called first. 2416 2417 final Constant c = cpg.getConstant(o.getIndex()); 2418 if (! ( ( c instanceof ConstantLong) || 2419 ( c instanceof ConstantDouble ) ) ) { 2420 constraintViolated(o, 2421 "Referenced constant should be a CONSTANT_Integer, a CONSTANT_Float or a CONSTANT_String, but is '"+c+"'."); 2422 } 2423 } 2424 2425 /** 2426 * Ensures the specific preconditions of the said instruction. 2427 */ 2428 @Override visitLDIV(final LDIV o)2429 public void visitLDIV(final LDIV o) { 2430 if (stack().peek() != Type.LONG) { 2431 constraintViolated(o, "The value at the stack top is not of type 'long', but of type '"+stack().peek()+"'."); 2432 } 2433 if (stack().peek(1) != Type.LONG) { 2434 constraintViolated(o, "The value at the stack next-to-top is not of type 'long', but of type '"+stack().peek(1)+"'."); 2435 } 2436 } 2437 2438 /** 2439 * Ensures the specific preconditions of the said instruction. 2440 */ 2441 @Override visitLLOAD(final LLOAD o)2442 public void visitLLOAD(final LLOAD o) { 2443 //visitLoadInstruction(LoadInstruction) is called before. 2444 2445 // Nothing else needs to be done here. 2446 } 2447 2448 /** 2449 * Ensures the specific preconditions of the said instruction. 2450 */ 2451 @Override visitLMUL(final LMUL o)2452 public void visitLMUL(final LMUL o) { 2453 if (stack().peek() != Type.LONG) { 2454 constraintViolated(o, "The value at the stack top is not of type 'long', but of type '"+stack().peek()+"'."); 2455 } 2456 if (stack().peek(1) != Type.LONG) { 2457 constraintViolated(o, "The value at the stack next-to-top is not of type 'long', but of type '"+stack().peek(1)+"'."); 2458 } 2459 } 2460 2461 /** 2462 * Ensures the specific preconditions of the said instruction. 2463 */ 2464 @Override visitLNEG(final LNEG o)2465 public void visitLNEG(final LNEG o) { 2466 if (stack().peek() != Type.LONG) { 2467 constraintViolated(o, "The value at the stack top is not of type 'long', but of type '"+stack().peek()+"'."); 2468 } 2469 } 2470 2471 /** 2472 * Ensures the specific preconditions of the said instruction. 2473 */ 2474 @Override visitLOOKUPSWITCH(final LOOKUPSWITCH o)2475 public void visitLOOKUPSWITCH(final LOOKUPSWITCH o) { 2476 if (stack().peek() != Type.INT) { 2477 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 2478 } 2479 // See also pass 3a. 2480 } 2481 2482 /** 2483 * Ensures the specific preconditions of the said instruction. 2484 */ 2485 @Override visitLOR(final LOR o)2486 public void visitLOR(final LOR o) { 2487 if (stack().peek() != Type.LONG) { 2488 constraintViolated(o, "The value at the stack top is not of type 'long', but of type '"+stack().peek()+"'."); 2489 } 2490 if (stack().peek(1) != Type.LONG) { 2491 constraintViolated(o, "The value at the stack next-to-top is not of type 'long', but of type '"+stack().peek(1)+"'."); 2492 } 2493 } 2494 2495 /** 2496 * Ensures the specific preconditions of the said instruction. 2497 */ 2498 @Override visitLREM(final LREM o)2499 public void visitLREM(final LREM o) { 2500 if (stack().peek() != Type.LONG) { 2501 constraintViolated(o, "The value at the stack top is not of type 'long', but of type '"+stack().peek()+"'."); 2502 } 2503 if (stack().peek(1) != Type.LONG) { 2504 constraintViolated(o, "The value at the stack next-to-top is not of type 'long', but of type '"+stack().peek(1)+"'."); 2505 } 2506 } 2507 2508 /** 2509 * Ensures the specific preconditions of the said instruction. 2510 */ 2511 @Override visitLRETURN(final LRETURN o)2512 public void visitLRETURN(final LRETURN o) { 2513 if (stack().peek() != Type.LONG) { 2514 constraintViolated(o, "The value at the stack top is not of type 'long', but of type '"+stack().peek()+"'."); 2515 } 2516 } 2517 2518 /** 2519 * Ensures the specific preconditions of the said instruction. 2520 */ 2521 @Override visitLSHL(final LSHL o)2522 public void visitLSHL(final LSHL o) { 2523 if (stack().peek() != Type.INT) { 2524 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 2525 } 2526 if (stack().peek(1) != Type.LONG) { 2527 constraintViolated(o, "The value at the stack next-to-top is not of type 'long', but of type '"+stack().peek(1)+"'."); 2528 } 2529 } 2530 2531 /** 2532 * Ensures the specific preconditions of the said instruction. 2533 */ 2534 @Override visitLSHR(final LSHR o)2535 public void visitLSHR(final LSHR o) { 2536 if (stack().peek() != Type.INT) { 2537 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 2538 } 2539 if (stack().peek(1) != Type.LONG) { 2540 constraintViolated(o, "The value at the stack next-to-top is not of type 'long', but of type '"+stack().peek(1)+"'."); 2541 } 2542 } 2543 2544 /** 2545 * Ensures the specific preconditions of the said instruction. 2546 */ 2547 @Override visitLSTORE(final LSTORE o)2548 public void visitLSTORE(final LSTORE o) { 2549 //visitStoreInstruction(StoreInstruction) is called before. 2550 2551 // Nothing else needs to be done here. 2552 } 2553 2554 /** 2555 * Ensures the specific preconditions of the said instruction. 2556 */ 2557 @Override visitLSUB(final LSUB o)2558 public void visitLSUB(final LSUB o) { 2559 if (stack().peek() != Type.LONG) { 2560 constraintViolated(o, "The value at the stack top is not of type 'long', but of type '"+stack().peek()+"'."); 2561 } 2562 if (stack().peek(1) != Type.LONG) { 2563 constraintViolated(o, "The value at the stack next-to-top is not of type 'long', but of type '"+stack().peek(1)+"'."); 2564 } 2565 } 2566 2567 /** 2568 * Ensures the specific preconditions of the said instruction. 2569 */ 2570 @Override visitLUSHR(final LUSHR o)2571 public void visitLUSHR(final LUSHR o) { 2572 if (stack().peek() != Type.INT) { 2573 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 2574 } 2575 if (stack().peek(1) != Type.LONG) { 2576 constraintViolated(o, "The value at the stack next-to-top is not of type 'long', but of type '"+stack().peek(1)+"'."); 2577 } 2578 } 2579 2580 /** 2581 * Ensures the specific preconditions of the said instruction. 2582 */ 2583 @Override visitLXOR(final LXOR o)2584 public void visitLXOR(final LXOR o) { 2585 if (stack().peek() != Type.LONG) { 2586 constraintViolated(o, "The value at the stack top is not of type 'long', but of type '"+stack().peek()+"'."); 2587 } 2588 if (stack().peek(1) != Type.LONG) { 2589 constraintViolated(o, "The value at the stack next-to-top is not of type 'long', but of type '"+stack().peek(1)+"'."); 2590 } 2591 } 2592 2593 /** 2594 * Ensures the specific preconditions of the said instruction. 2595 */ 2596 @Override visitMONITORENTER(final MONITORENTER o)2597 public void visitMONITORENTER(final MONITORENTER o) { 2598 if (! ((stack().peek()) instanceof ReferenceType)) { 2599 constraintViolated(o, "The stack top should be of a ReferenceType, but is '"+stack().peek()+"'."); 2600 } 2601 //referenceTypeIsInitialized(o, (ReferenceType) (stack().peek()) ); 2602 } 2603 2604 /** 2605 * Ensures the specific preconditions of the said instruction. 2606 */ 2607 @Override visitMONITOREXIT(final MONITOREXIT o)2608 public void visitMONITOREXIT(final MONITOREXIT o) { 2609 if (! ((stack().peek()) instanceof ReferenceType)) { 2610 constraintViolated(o, "The stack top should be of a ReferenceType, but is '"+stack().peek()+"'."); 2611 } 2612 //referenceTypeIsInitialized(o, (ReferenceType) (stack().peek()) ); 2613 } 2614 2615 /** 2616 * Ensures the specific preconditions of the said instruction. 2617 */ 2618 @Override visitMULTIANEWARRAY(final MULTIANEWARRAY o)2619 public void visitMULTIANEWARRAY(final MULTIANEWARRAY o) { 2620 final int dimensions = o.getDimensions(); 2621 // Dimensions argument is okay: see Pass 3a. 2622 for (int i=0; i<dimensions; i++) { 2623 if (stack().peek(i) != Type.INT) { 2624 constraintViolated(o, "The '"+dimensions+"' upper stack types should be 'int' but aren't."); 2625 } 2626 } 2627 // The runtime constant pool item at that index must be a symbolic reference to a class, 2628 // array, or interface type. See Pass 3a. 2629 } 2630 2631 /** 2632 * Ensures the specific preconditions of the said instruction. 2633 */ 2634 @Override visitNEW(final NEW o)2635 public void visitNEW(final NEW o) { 2636 //visitCPInstruction(CPInstruction) has been called before. 2637 //visitLoadClass(LoadClass) has been called before. 2638 2639 final Type t = o.getType(cpg); 2640 if (! (t instanceof ReferenceType)) { 2641 throw new AssertionViolatedException("NEW.getType() returning a non-reference type?!"); 2642 } 2643 if (! (t instanceof ObjectType)) { 2644 constraintViolated(o, "Expecting a class type (ObjectType) to work on. Found: '"+t+"'."); 2645 } 2646 final ObjectType obj = (ObjectType) t; 2647 2648 //e.g.: Don't instantiate interfaces 2649 try { 2650 if (! obj.referencesClassExact()) { 2651 constraintViolated(o, "Expecting a class type (ObjectType) to work on. Found: '"+obj+"'."); 2652 } 2653 } catch (final ClassNotFoundException e) { 2654 constraintViolated(o, "Expecting a class type (ObjectType) to work on. Found: '"+obj+"'." + " which threw " + e); 2655 } 2656 } 2657 2658 /** 2659 * Ensures the specific preconditions of the said instruction. 2660 */ 2661 @Override visitNEWARRAY(final NEWARRAY o)2662 public void visitNEWARRAY(final NEWARRAY o) { 2663 if (stack().peek() != Type.INT) { 2664 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 2665 } 2666 } 2667 2668 /** 2669 * Ensures the specific preconditions of the said instruction. 2670 */ 2671 @Override visitNOP(final NOP o)2672 public void visitNOP(final NOP o) { 2673 // nothing is to be done here. 2674 } 2675 2676 /** 2677 * Ensures the specific preconditions of the said instruction. 2678 */ 2679 @Override visitPOP(final POP o)2680 public void visitPOP(final POP o) { 2681 if (stack().peek().getSize() != 1) { 2682 constraintViolated(o, 2683 "Stack top size should be 1 but stack top is '"+stack().peek()+"' of size '"+stack().peek().getSize()+"'."); 2684 } 2685 } 2686 2687 /** 2688 * Ensures the specific preconditions of the said instruction. 2689 */ 2690 @Override visitPOP2(final POP2 o)2691 public void visitPOP2(final POP2 o) { 2692 if (stack().peek().getSize() != 2) { 2693 constraintViolated(o, 2694 "Stack top size should be 2 but stack top is '"+stack().peek()+"' of size '"+stack().peek().getSize()+"'."); 2695 } 2696 } 2697 2698 /** 2699 * Ensures the specific preconditions of the said instruction. 2700 */ 2701 @Override visitPUTFIELD(final PUTFIELD o)2702 public void visitPUTFIELD(final PUTFIELD o) { 2703 try { 2704 2705 final Type objectref = stack().peek(1); 2706 if (! ( (objectref instanceof ObjectType) || (objectref == Type.NULL) ) ) { 2707 constraintViolated(o, 2708 "Stack next-to-top should be an object reference that's not an array reference, but is '"+objectref+"'."); 2709 } 2710 2711 final String field_name = o.getFieldName(cpg); 2712 2713 final JavaClass jc = Repository.lookupClass(getObjectType(o).getClassName()); 2714 final Field[] fields = jc.getFields(); 2715 Field f = null; 2716 for (final Field field : fields) { 2717 if (field.getName().equals(field_name)) { 2718 final Type f_type = Type.getType(field.getSignature()); 2719 final Type o_type = o.getType(cpg); 2720 /* TODO: Check if assignment compatibility is sufficient. 2721 * What does Sun do? 2722 */ 2723 if (f_type.equals(o_type)) { 2724 f = field; 2725 break; 2726 } 2727 } 2728 } 2729 if (f == null) { 2730 throw new AssertionViolatedException("Field '" + field_name + "' not found in " + jc.getClassName()); 2731 } 2732 2733 final Type value = stack().peek(); 2734 final Type t = Type.getType(f.getSignature()); 2735 Type shouldbe = t; 2736 if (shouldbe == Type.BOOLEAN || 2737 shouldbe == Type.BYTE || 2738 shouldbe == Type.CHAR || 2739 shouldbe == Type.SHORT) { 2740 shouldbe = Type.INT; 2741 } 2742 if (t instanceof ReferenceType) { 2743 ReferenceType rvalue = null; 2744 if (value instanceof ReferenceType) { 2745 rvalue = (ReferenceType) value; 2746 referenceTypeIsInitialized(o, rvalue); 2747 } 2748 else{ 2749 constraintViolated(o, "The stack top type '"+value+"' is not of a reference type as expected."); 2750 } 2751 // TODO: This can possibly only be checked using Staerk-et-al's "set-of-object types", not 2752 // using "wider cast object types" created during verification. 2753 // Comment it out if you encounter problems. See also the analogon at visitPUTSTATIC. 2754 if (!(rvalue.isAssignmentCompatibleWith(shouldbe))) { 2755 constraintViolated(o, "The stack top type '"+value+"' is not assignment compatible with '"+shouldbe+"'."); 2756 } 2757 } 2758 else{ 2759 if (shouldbe != value) { 2760 constraintViolated(o, "The stack top type '"+value+"' is not of type '"+shouldbe+"' as expected."); 2761 } 2762 } 2763 2764 if (f.isProtected()) { 2765 final ObjectType classtype = getObjectType(o); 2766 final ObjectType curr = ObjectType.getInstance(mg.getClassName()); 2767 2768 if ( classtype.equals(curr) || 2769 curr.subclassOf(classtype) ) { 2770 final Type tp = stack().peek(1); 2771 if (tp == Type.NULL) { 2772 return; 2773 } 2774 if (! (tp instanceof ObjectType) ) { 2775 constraintViolated(o, "The 'objectref' must refer to an object that's not an array. Found instead: '"+tp+"'."); 2776 } 2777 final ObjectType objreftype = (ObjectType) tp; 2778 if (! ( objreftype.equals(curr) || 2779 objreftype.subclassOf(curr) ) ) { 2780 constraintViolated(o, 2781 "The referenced field has the ACC_PROTECTED modifier, and it's a member of the current class or"+ 2782 " a superclass of the current class. However, the referenced object type '"+stack().peek()+ 2783 "' is not the current class or a subclass of the current class."); 2784 } 2785 } 2786 } 2787 2788 // TODO: Could go into Pass 3a. 2789 if (f.isStatic()) { 2790 constraintViolated(o, "Referenced field '"+f+"' is static which it shouldn't be."); 2791 } 2792 2793 } catch (final ClassNotFoundException e) { 2794 // FIXME: maybe not the best way to handle this 2795 throw new AssertionViolatedException("Missing class: " + e, e); 2796 } 2797 } 2798 2799 /** 2800 * Ensures the specific preconditions of the said instruction. 2801 */ 2802 @Override visitPUTSTATIC(final PUTSTATIC o)2803 public void visitPUTSTATIC(final PUTSTATIC o) { 2804 try { 2805 final String field_name = o.getFieldName(cpg); 2806 final JavaClass jc = Repository.lookupClass(getObjectType(o).getClassName()); 2807 final Field[] fields = jc.getFields(); 2808 Field f = null; 2809 for (final Field field : fields) { 2810 if (field.getName().equals(field_name)) { 2811 final Type f_type = Type.getType(field.getSignature()); 2812 final Type o_type = o.getType(cpg); 2813 /* TODO: Check if assignment compatibility is sufficient. 2814 * What does Sun do? 2815 */ 2816 if (f_type.equals(o_type)) { 2817 f = field; 2818 break; 2819 } 2820 } 2821 } 2822 if (f == null) { 2823 throw new AssertionViolatedException("Field '" + field_name + "' not found in " + jc.getClassName()); 2824 } 2825 final Type value = stack().peek(); 2826 final Type t = Type.getType(f.getSignature()); 2827 Type shouldbe = t; 2828 if (shouldbe == Type.BOOLEAN || 2829 shouldbe == Type.BYTE || 2830 shouldbe == Type.CHAR || 2831 shouldbe == Type.SHORT) { 2832 shouldbe = Type.INT; 2833 } 2834 if (t instanceof ReferenceType) { 2835 ReferenceType rvalue = null; 2836 if (value instanceof ReferenceType) { 2837 rvalue = (ReferenceType) value; 2838 referenceTypeIsInitialized(o, rvalue); 2839 } 2840 else{ 2841 constraintViolated(o, "The stack top type '"+value+"' is not of a reference type as expected."); 2842 } 2843 // TODO: This can possibly only be checked using Staerk-et-al's "set-of-object types", not 2844 // using "wider cast object types" created during verification. 2845 // Comment it out if you encounter problems. See also the analogon at visitPUTFIELD. 2846 if (!(rvalue.isAssignmentCompatibleWith(shouldbe))) { 2847 constraintViolated(o, "The stack top type '"+value+"' is not assignment compatible with '"+shouldbe+"'."); 2848 } 2849 } 2850 else{ 2851 if (shouldbe != value) { 2852 constraintViolated(o, "The stack top type '"+value+"' is not of type '"+shouldbe+"' as expected."); 2853 } 2854 } 2855 // TODO: Interface fields may be assigned to only once. (Hard to implement in 2856 // JustIce's execution model). This may only happen in <clinit>, see Pass 3a. 2857 2858 } catch (final ClassNotFoundException e) { 2859 // FIXME: maybe not the best way to handle this 2860 throw new AssertionViolatedException("Missing class: " + e, e); 2861 } 2862 } 2863 2864 /** 2865 * Ensures the specific preconditions of the said instruction. 2866 */ 2867 @Override visitRET(final RET o)2868 public void visitRET(final RET o) { 2869 if (! (locals().get(o.getIndex()) instanceof ReturnaddressType)) { 2870 constraintViolated(o, "Expecting a ReturnaddressType in local variable "+o.getIndex()+"."); 2871 } 2872 if (locals().get(o.getIndex()) == ReturnaddressType.NO_TARGET) { 2873 throw new AssertionViolatedException("Oops: RET expecting a target!"); 2874 } 2875 // Other constraints such as non-allowed overlapping subroutines are enforced 2876 // while building the Subroutines data structure. 2877 } 2878 2879 /** 2880 * Ensures the specific preconditions of the said instruction. 2881 */ 2882 @Override visitRETURN(final RETURN o)2883 public void visitRETURN(final RETURN o) { 2884 if (mg.getName().equals(Const.CONSTRUCTOR_NAME)) {// If we leave an <init> method 2885 if ((Frame.getThis() != null) && (!(mg.getClassName().equals(Type.OBJECT.getClassName()))) ) { 2886 constraintViolated(o, "Leaving a constructor that itself did not call a constructor."); 2887 } 2888 } 2889 } 2890 2891 /** 2892 * Ensures the specific preconditions of the said instruction. 2893 */ 2894 @Override visitSALOAD(final SALOAD o)2895 public void visitSALOAD(final SALOAD o) { 2896 indexOfInt(o, stack().peek()); 2897 if (stack().peek(1) == Type.NULL) { 2898 return; 2899 } 2900 if (! (stack().peek(1) instanceof ArrayType)) { 2901 constraintViolated(o, "Stack next-to-top must be of type short[] but is '"+stack().peek(1)+"'."); 2902 } 2903 final Type t = ((ArrayType) (stack().peek(1))).getBasicType(); 2904 if (t != Type.SHORT) { 2905 constraintViolated(o, "Stack next-to-top must be of type short[] but is '"+stack().peek(1)+"'."); 2906 } 2907 } 2908 2909 /** 2910 * Ensures the specific preconditions of the said instruction. 2911 */ 2912 @Override visitSASTORE(final SASTORE o)2913 public void visitSASTORE(final SASTORE o) { 2914 if (stack().peek() != Type.INT) { 2915 constraintViolated(o, "The value at the stack top is not of type 'int', but of type '"+stack().peek()+"'."); 2916 } 2917 indexOfInt(o, stack().peek(1)); 2918 if (stack().peek(2) == Type.NULL) { 2919 return; 2920 } 2921 if (! (stack().peek(2) instanceof ArrayType)) { 2922 constraintViolated(o, "Stack next-to-next-to-top must be of type short[] but is '"+stack().peek(2)+"'."); 2923 } 2924 final Type t = ((ArrayType) (stack().peek(2))).getBasicType(); 2925 if (t != Type.SHORT) { 2926 constraintViolated(o, "Stack next-to-next-to-top must be of type short[] but is '"+stack().peek(2)+"'."); 2927 } 2928 } 2929 2930 /** 2931 * Ensures the specific preconditions of the said instruction. 2932 */ 2933 @Override visitSIPUSH(final SIPUSH o)2934 public void visitSIPUSH(final SIPUSH o) { 2935 // nothing to do here. Generic visitXXX() methods did the trick before. 2936 } 2937 2938 /** 2939 * Ensures the specific preconditions of the said instruction. 2940 */ 2941 @Override visitSWAP(final SWAP o)2942 public void visitSWAP(final SWAP o) { 2943 if (stack().peek().getSize() != 1) { 2944 constraintViolated(o, "The value at the stack top is not of size '1', but of size '"+stack().peek().getSize()+"'."); 2945 } 2946 if (stack().peek(1).getSize() != 1) { 2947 constraintViolated(o, 2948 "The value at the stack next-to-top is not of size '1', but of size '"+stack().peek(1).getSize()+"'."); 2949 } 2950 } 2951 2952 /** 2953 * Ensures the specific preconditions of the said instruction. 2954 */ 2955 @Override visitTABLESWITCH(final TABLESWITCH o)2956 public void visitTABLESWITCH(final TABLESWITCH o) { 2957 indexOfInt(o, stack().peek()); 2958 // See Pass 3a. 2959 } 2960 2961 } 2962 2963