You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

InstConstraintVisitor.java 93KB

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