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