⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pass3averifier.java

📁 Java Bytecode Editor 是一个 JAVA 的字节码反汇编和修改器。它可以很方便的修改已经编译成 Class 文件的 JAVA 文件。
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
package org.apache.bcel.verifier.statics;

/* ====================================================================
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Apache" and "Apache Software Foundation" and
 *    "Apache BCEL" must not be used to endorse or promote products
 *    derived from this software without prior written permission. For
 *    written permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    "Apache BCEL", nor may "Apache" appear in their name, without
 *    prior written permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

import org.apache.bcel.*;
import org.apache.bcel.generic.*;
import org.apache.bcel.classfile.*;
import org.apache.bcel.verifier.*;
import org.apache.bcel.verifier.exc.*;

/**
 * This PassVerifier verifies a class file according to
 * pass 3, static part as described in The Java Virtual
 * Machine Specification, 2nd edition.
 * More detailed information is to be found at the do_verify()
 * method's documentation. 
 *
 * @version $Id: Pass3aVerifier.java,v 1.1 2005/12/16 14:11:30 andos Exp $
 * @author <A HREF="http://www.inf.fu-berlin.de/~ehaase"/>Enver Haase</A>
 * @see #do_verify()
 */
public final class Pass3aVerifier extends PassVerifier{

	/** The Verifier that created this. */
	private Verifier myOwner;

	/** 
	 * The method number to verify.
	 * This is the index in the array returned
	 * by JavaClass.getMethods().
	 */
	private int method_no;

	/** The one and only InstructionList object used by an instance of this class. It's here for performance reasons by do_verify() and its callees. */	
	InstructionList instructionList;
	/** The one and only Code object used by an instance of this class. It's here for performance reasons by do_verify() and its callees. */	
	Code code;

	/** Should only be instantiated by a Verifier. */
	public Pass3aVerifier(Verifier owner, int method_no){
		myOwner = owner;
		this.method_no = method_no;
	}

	/**
	 * Pass 3a is the verification of static constraints of
	 * JVM code (such as legal targets of branch instructions).
	 * This is the part of pass 3 where you do not need data
	 * flow analysis.
	 * JustIce also delays the checks for a correct exception
	 * table of a Code attribute and correct line number entries
	 * in a LineNumberTable attribute of a Code attribute (which
	 * conceptually belong to pass 2) to this pass. Also, most
	 * of the check for valid local variable entries in a
	 * LocalVariableTable attribute of a Code attribute is
	 * delayed until this pass.
	 * All these checks need access to the code array of the
	 * Code attribute.
	 *
	 * @throws InvalidMethodException if the method to verify does not exist.
	 */
	public VerificationResult do_verify(){
		if (myOwner.doPass2().equals(VerificationResult.VR_OK)){
			// Okay, class file was loaded correctly by Pass 1
			// and satisfies static constraints of Pass 2.
			JavaClass jc = Repository.lookupClass(myOwner.getClassName());
			Method[] methods = jc.getMethods();
			if (method_no >= methods.length){
				throw new InvalidMethodException("METHOD DOES NOT EXIST!");
			}
			Method method = methods[method_no];
			code = method.getCode();
			
			// No Code? Nothing to verify!
			if ( method.isAbstract() || method.isNative() ){ // IF mg HAS NO CODE (static constraint of Pass 2)
				return VerificationResult.VR_OK;
			}

			// TODO:
			// We want a very sophisticated code examination here with good explanations
			// on where to look for an illegal instruction or such.
			// Only after that we should try to build an InstructionList and throw an
			// AssertionViolatedException if after our examination InstructionList building
			// still fails.
			// That examination should be implemented in a byte-oriented way, i.e. look for
			// an instruction, make sure its validity, count its length, find the next
			// instruction and so on.
			try{
				instructionList = new InstructionList(method.getCode().getCode());
			}
			catch(RuntimeException re){
				return new VerificationResult(VerificationResult.VERIFIED_REJECTED, "Bad bytecode in the code array of the Code attribute of method '"+method+"'.");
			}
			
			instructionList.setPositions(true);

			// Start verification.
			VerificationResult vr = VerificationResult.VR_OK; //default
			try{
				delayedPass2Checks();
			}
			catch(ClassConstraintException cce){
				vr = new VerificationResult(VerificationResult.VERIFIED_REJECTED, cce.getMessage());
				return vr;
			}
			try{
				pass3StaticInstructionChecks();
				pass3StaticInstructionOperandsChecks();
			}
			catch(StaticCodeConstraintException scce){
				vr = new VerificationResult(VerificationResult.VERIFIED_REJECTED, scce.getMessage());
			}
			return vr;
		}
		else{ //did not pass Pass 2.
			return VerificationResult.VR_NOTYET;
		}
	}

	/**
	 * These are the checks that could be done in pass 2 but are delayed to pass 3
	 * for performance reasons. Also, these checks need access to the code array
	 * of the Code attribute of a Method so it's okay to perform them here.
	 * Also see the description of the do_verify() method.
	 *
	 * @throws ClassConstraintException if the verification fails.
	 * @see #do_verify()
	 */
	private void delayedPass2Checks(){

		int[] instructionPositions = instructionList.getInstructionPositions();
		int codeLength = code.getCode().length;

		/////////////////////
		// LineNumberTable //
		/////////////////////
		LineNumberTable lnt = code.getLineNumberTable();
		if (lnt != null){
			LineNumber[] lineNumbers = lnt.getLineNumberTable();
			IntList offsets = new IntList();
			lineNumber_loop: for (int i=0; i < lineNumbers.length; i++){ // may appear in any order.
				for (int j=0; j < instructionPositions.length; j++){
					// TODO: Make this a binary search! The instructionPositions array is naturally ordered!
					int offset = lineNumbers[i].getStartPC();
					if (instructionPositions[j] == offset){
						if (offsets.contains(offset)){
							addMessage("LineNumberTable attribute '"+code.getLineNumberTable()+"' refers to the same code offset ('"+offset+"') more than once which is violating the semantics [but is sometimes produced by IBM's 'jikes' compiler].");
						}
						else{
							offsets.add(offset);
						}
						continue lineNumber_loop;
					}
				}
				throw new ClassConstraintException("Code attribute '"+code+"' has a LineNumberTable attribute '"+code.getLineNumberTable()+"' referring to a code offset ('"+lineNumbers[i].getStartPC()+"') that does not exist.");
			}
		}

		///////////////////////////
		// LocalVariableTable(s) //
		///////////////////////////
		/* We cannot use code.getLocalVariableTable() because there could be more
		   than only one. This is a bug in BCEL. */
		Attribute[] atts = code.getAttributes();
		for (int a=0; a<atts.length; a++){
			if (atts[a] instanceof LocalVariableTable){
				LocalVariableTable lvt = (LocalVariableTable) atts[a];
				if (lvt != null){
					LocalVariable[] localVariables = lvt.getLocalVariableTable();
					for (int i=0; i<localVariables.length; i++){
						int startpc = localVariables[i].getStartPC();
						int length  = localVariables[i].getLength();
				
						if (!contains(instructionPositions, startpc)){
							throw new ClassConstraintException("Code attribute '"+code+"' has a LocalVariableTable attribute '"+code.getLocalVariableTable()+"' referring to a code offset ('"+startpc+"') that does not exist.");
						}
						if ( (!contains(instructionPositions, startpc+length)) && (startpc+length != codeLength) ){
							throw new ClassConstraintException("Code attribute '"+code+"' has a LocalVariableTable attribute '"+code.getLocalVariableTable()+"' referring to a code offset start_pc+length ('"+(startpc+length)+"') that does not exist.");
						}
					}
				}
			}
		}
		
		////////////////////
		// ExceptionTable //
		////////////////////
		// In BCEL's "classfile" API, the startPC/endPC-notation is
		// inclusive/exclusive as in the Java Virtual Machine Specification.
		// WARNING: This is not true for BCEL's "generic" API.
		CodeException[] exceptionTable = code.getExceptionTable();
		for (int i=0; i<exceptionTable.length; i++){
			int startpc = exceptionTable[i].getStartPC();
			int endpc = exceptionTable[i].getEndPC();
			int handlerpc = exceptionTable[i].getHandlerPC();
			if (startpc >= endpc){
				throw new ClassConstraintException("Code attribute '"+code+"' has an exception_table entry '"+exceptionTable[i]+"' that has its start_pc ('"+startpc+"') not smaller than its end_pc ('"+endpc+"').");
			}
			if (!contains(instructionPositions, startpc)){
				throw new ClassConstraintException("Code attribute '"+code+"' has an exception_table entry '"+exceptionTable[i]+"' that has a non-existant bytecode offset as its start_pc ('"+startpc+"').");
			}
			if ( (!contains(instructionPositions, endpc)) && (endpc != codeLength)){
				throw new ClassConstraintException("Code attribute '"+code+"' has an exception_table entry '"+exceptionTable[i]+"' that has a non-existant bytecode offset as its end_pc ('"+startpc+"') [that is also not equal to code_length ('"+codeLength+"')].");
			}
			if (!contains(instructionPositions, handlerpc)){
				throw new ClassConstraintException("Code attribute '"+code+"' has an exception_table entry '"+exceptionTable[i]+"' that has a non-existant bytecode offset as its handler_pc ('"+handlerpc+"').");
			}
		}
	}

	/**
	 * These are the checks if constraints are satisfied which are described in the
	 * Java Virtual Machine Specification, Second Edition as Static Constraints on
	 * the instructions of Java Virtual Machine Code (chapter 4.8.1).
	 *
	 * @throws StaticCodeConstraintException if the verification fails.
	 */
	private void pass3StaticInstructionChecks(){
		
		// Code array must not be empty:
		// Enforced in pass 2 (also stated in the static constraints of the Code
		// array in vmspec2), together with pass 1 (reading code_length bytes and
		// interpreting them as code[]). So this must not be checked again here.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -