1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 package org.apache.bcel.verifier; 19 20 import java.util.ArrayList; 21 import java.util.HashMap; 22 import java.util.List; 23 import java.util.Map; 24 25 import org.apache.bcel.classfile.JavaClass; 26 import org.apache.bcel.verifier.statics.Pass1Verifier; 27 import org.apache.bcel.verifier.statics.Pass2Verifier; 28 import org.apache.bcel.verifier.statics.Pass3aVerifier; 29 import org.apache.bcel.verifier.structurals.Pass3bVerifier; 30 31 /** 32 * A Verifier instance is there to verify a class file according to The Java Virtual 33 * Machine Specification, 2nd Edition. 34 * 35 * Pass-3b-verification includes pass-3a-verification; 36 * pass-3a-verification includes pass-2-verification; 37 * pass-2-verification includes pass-1-verification. 38 * 39 * A Verifier creates PassVerifier instances to perform the actual verification. 40 * Verifier instances are usually generated by the VerifierFactory. 41 * 42 * @version $Id$ 43 * @see VerifierFactory 44 * @see PassVerifier 45 */ 46 public class Verifier { 47 48 /** 49 * The name of the class this verifier operates on. 50 */ 51 private final String classname; 52 /** A Pass1Verifier for this Verifier instance. */ 53 private Pass1Verifier p1v; 54 /** A Pass2Verifier for this Verifier instance. */ 55 private Pass2Verifier p2v; 56 /** The Pass3aVerifiers for this Verifier instance. Key: Interned string specifying the method number. */ 57 private final Map<String, Pass3aVerifier> p3avs = new HashMap<>(); 58 /** The Pass3bVerifiers for this Verifier instance. Key: Interned string specifying the method number. */ 59 private final Map<String, Pass3bVerifier> p3bvs = new HashMap<>(); 60 61 62 /** Returns the VerificationResult for the given pass. */ doPass1()63 public VerificationResult doPass1() { 64 if (p1v == null) { 65 p1v = new Pass1Verifier(this); 66 } 67 return p1v.verify(); 68 } 69 70 71 /** Returns the VerificationResult for the given pass. */ doPass2()72 public VerificationResult doPass2() { 73 if (p2v == null) { 74 p2v = new Pass2Verifier(this); 75 } 76 return p2v.verify(); 77 } 78 79 80 /** Returns the VerificationResult for the given pass. */ doPass3a( final int method_no )81 public VerificationResult doPass3a( final int method_no ) { 82 final String key = Integer.toString(method_no); 83 Pass3aVerifier p3av; 84 p3av = p3avs.get(key); 85 if (p3avs.get(key) == null) { 86 p3av = new Pass3aVerifier(this, method_no); 87 p3avs.put(key, p3av); 88 } 89 return p3av.verify(); 90 } 91 92 93 /** Returns the VerificationResult for the given pass. */ doPass3b( final int method_no )94 public VerificationResult doPass3b( final int method_no ) { 95 final String key = Integer.toString(method_no); 96 Pass3bVerifier p3bv; 97 p3bv = p3bvs.get(key); 98 if (p3bvs.get(key) == null) { 99 p3bv = new Pass3bVerifier(this, method_no); 100 p3bvs.put(key, p3bv); 101 } 102 return p3bv.verify(); 103 } 104 105 106 /** 107 * Instantiation is done by the VerifierFactory. 108 * 109 * @see VerifierFactory 110 */ Verifier(final String fully_qualified_classname)111 Verifier(final String fully_qualified_classname) { 112 classname = fully_qualified_classname; 113 flush(); 114 } 115 116 117 /** 118 * Returns the name of the class this verifier operates on. 119 * This is particularly interesting when this verifier was created 120 * recursively by another Verifier and you got a reference to this 121 * Verifier by the getVerifiers() method of the VerifierFactory. 122 * @see VerifierFactory 123 */ getClassName()124 public final String getClassName() { 125 return classname; 126 } 127 128 129 /** 130 * Forget everything known about the class file; that means, really 131 * start a new verification of a possibly different class file from 132 * BCEL's repository. 133 * 134 */ flush()135 public void flush() { 136 p1v = null; 137 p2v = null; 138 p3avs.clear(); 139 p3bvs.clear(); 140 } 141 142 143 /** 144 * This returns all the (warning) messages collected during verification. 145 * A prefix shows from which verifying pass a message originates. 146 */ getMessages()147 public String[] getMessages() throws ClassNotFoundException { 148 final List<String> messages = new ArrayList<>(); 149 if (p1v != null) { 150 final String[] p1m = p1v.getMessages(); 151 for (final String element : p1m) { 152 messages.add("Pass 1: " + element); 153 } 154 } 155 if (p2v != null) { 156 final String[] p2m = p2v.getMessages(); 157 for (final String element : p2m) { 158 messages.add("Pass 2: " + element); 159 } 160 } 161 for (final Pass3aVerifier pv : p3avs.values()) { 162 final String[] p3am = pv.getMessages(); 163 final int meth = pv.getMethodNo(); 164 for (final String element : p3am) { 165 messages.add("Pass 3a, method " + meth + " ('" 166 + org.apache.bcel.Repository.lookupClass(classname).getMethods()[meth] 167 + "'): " + element); 168 } 169 } 170 for (final Pass3bVerifier pv : p3bvs.values()) { 171 final String[] p3bm = pv.getMessages(); 172 final int meth = pv.getMethodNo(); 173 for (final String element : p3bm) { 174 messages.add("Pass 3b, method " + meth + " ('" 175 + org.apache.bcel.Repository.lookupClass(classname).getMethods()[meth] 176 + "'): " + element); 177 } 178 } 179 180 return messages.toArray(new String[messages.size()]); 181 } 182 183 184 /** 185 * Verifies class files. 186 * This is a simple demonstration of how the API of BCEL's 187 * class file verifier "JustIce" may be used. 188 * You should supply command-line arguments which are 189 * fully qualified namea of the classes to verify. These class files 190 * must be somewhere in your CLASSPATH (refer to Sun's 191 * documentation for questions about this) or you must have put the classes 192 * into the BCEL Repository yourself (via 'addClass(JavaClass)'). 193 */ main( final String[] args )194 public static void main( final String[] args ) { 195 System.out 196 .println("JustIce by Enver Haase, (C) 2001-2002.\n<http://bcel.sourceforge.net>\n<http://commons.apache.org/bcel>\n"); 197 for (int k = 0; k < args.length; k++) { 198 try { 199 if (args[k].endsWith(".class")) { 200 final int dotclasspos = args[k].lastIndexOf(".class"); 201 if (dotclasspos != -1) { 202 args[k] = args[k].substring(0, dotclasspos); 203 } 204 } 205 args[k] = args[k].replace('/', '.'); 206 System.out.println("Now verifying: " + args[k] + "\n"); 207 final Verifier v = VerifierFactory.getVerifier(args[k]); 208 VerificationResult vr; 209 vr = v.doPass1(); 210 System.out.println("Pass 1:\n" + vr); 211 vr = v.doPass2(); 212 System.out.println("Pass 2:\n" + vr); 213 if (vr == VerificationResult.VR_OK) { 214 final JavaClass jc = org.apache.bcel.Repository.lookupClass(args[k]); 215 for (int i = 0; i < jc.getMethods().length; i++) { 216 vr = v.doPass3a(i); 217 System.out.println("Pass 3a, method number " + i + " ['" 218 + jc.getMethods()[i] + "']:\n" + vr); 219 vr = v.doPass3b(i); 220 System.out.println("Pass 3b, method number " + i + " ['" 221 + jc.getMethods()[i] + "']:\n" + vr); 222 } 223 } 224 System.out.println("Warnings:"); 225 final String[] warnings = v.getMessages(); 226 if (warnings.length == 0) { 227 System.out.println("<none>"); 228 } 229 for (final String warning : warnings) { 230 System.out.println(warning); 231 } 232 System.out.println("\n"); 233 // avoid swapping. 234 v.flush(); 235 org.apache.bcel.Repository.clearCache(); 236 System.gc(); 237 } catch (final ClassNotFoundException e) { 238 e.printStackTrace(); 239 } 240 } 241 } 242 } 243