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