All Downloads are FREE. Search and download functionalities are using the official Maven repository.

prompto.verifier.StackMapReader Maven / Gradle / Ivy

The newest version!
package prompto.verifier;

import java.util.concurrent.atomic.AtomicInteger;

import prompto.compiler.ClassConstant;
import prompto.compiler.IConstantOperand;
import prompto.compiler.MethodInfo;

public class StackMapReader {

	ClassVerifier _verifier;
	ByteReader _stream;
	byte[] _code_data;
	int _code_length;
	int _frame_count;
	
	public StackMapReader(ClassVerifier verifier, MethodInfo method, byte[] code_data, int code_length) {
		 this._verifier = verifier;
		 this._code_data = code_data;
		 this._code_length = code_length;
		 if(method.getCodeAttribute().getStackMapTable()!=null) {
			  byte[] stackmap_data = method.getCodeAttribute().getStackMapTable().getData();
			  _stream = new ByteReader(stackmap_data, 6);
			  _frame_count = _stream.get_u2();
		 } else {
			 // There's no stackmap table present. Frame count and size are 0.
			 _frame_count = 0;
		 }
	}

	public int get_frame_count() {
		return _frame_count;
	}

	public StackMapFrame next(StackMapFrame pre_frame, boolean first, int max_locals, int max_stack) {
		  StackMapFrame frame;
		  int offset;
		  VerificationType[] locals = null;
		  int frame_type = _stream.get_u1();
		  if (frame_type < 64) {
		    // same_frame
		    if (first) {
		      offset = frame_type;
		      // Can't share the locals array since that is updated by the verifier.
		      if (pre_frame.locals_size() > 0) {
		        locals = new VerificationType[pre_frame.locals_size()];
		      }
		    } else {
		      offset = pre_frame.offset() + frame_type + 1;
		      locals = pre_frame.locals();
		    }
		    frame = new StackMapFrame(
		      offset, pre_frame.flags(), pre_frame.locals_size(), 0,
		      max_locals, max_stack, locals, null, _verifier);
		    if (first && locals != null) {
		      frame.copy_locals(pre_frame);
		    }
		    return frame;
		  }
		  if (frame_type < 128) {
		    // same_locals_1_stack_item_frame
		    if (first) {
		      offset = frame_type - 64;
		      // Can't share the locals array since that is updated by the verifier.
		      if (pre_frame.locals_size() > 0) {
		        locals = new VerificationType[pre_frame.locals_size()];
		      }
		    } else {
		      offset = pre_frame.offset() + frame_type - 63;
		      locals = pre_frame.locals();
		    }
		    VerificationType[] stack = new VerificationType[2];
		    int stack_size = 1;
		    stack[0] = parse_verification_type(null);
		    if (stack[0].is_category2()) {
		      stack[1] = stack[0].to_category2_2nd();
		      stack_size = 2;
		    }
		    check_verification_type_array_size( stack_size, max_stack);
		    frame = new StackMapFrame(
		      offset, pre_frame.flags(), pre_frame.locals_size(), stack_size,
		      max_locals, max_stack, locals, stack, _verifier);
		    if (first && locals != null) {
		      frame.copy_locals(pre_frame);
		    }
		    return frame;
		  }

		  int offset_delta = _stream.get_u2();

		  if (frame_type < StackMapTable.SAME_LOCALS_1_STACK_ITEM_EXTENDED) {
			  throw new VerifierException("reserved frame type");
		  }

		  if (frame_type == StackMapTable.SAME_LOCALS_1_STACK_ITEM_EXTENDED) {
		    // same_locals_1_stack_item_frame_extended
		    if (first) {
		      offset = offset_delta;
		      // Can't share the locals array since that is updated by the verifier.
		      if (pre_frame.locals_size() > 0) {
		        locals = new VerificationType[pre_frame.locals_size()];
		      }
		    } else {
		      offset = pre_frame.offset() + offset_delta + 1;
		      locals = pre_frame.locals();
		    }
		    VerificationType[] stack = new VerificationType[2];
		    int stack_size = 1;
		    stack[0] = parse_verification_type(null);
		    if (stack[0].is_category2()) {
		      stack[1] = stack[0].to_category2_2nd();
		      stack_size = 2;
		    }
		    check_verification_type_array_size(stack_size, max_stack);
		    frame = new StackMapFrame(
		      offset, pre_frame.flags(), pre_frame.locals_size(), stack_size,
		      max_locals, max_stack, locals, stack, _verifier);
		    if (first && locals != null) {
		      frame.copy_locals(pre_frame);
		    }
		    return frame;
		  }

		  if (frame_type <= StackMapTable.SAME_EXTENDED) {
		    // chop_frame or same_frame_extended
		    locals = pre_frame.locals();
		    int length = pre_frame.locals_size();
		    int chops = StackMapTable.SAME_EXTENDED - frame_type;
		    int new_length = length;
		    byte flags = pre_frame.flags();
		    if (chops != 0) {
		      new_length = chop(locals, length, chops);
		      check_verification_type_array_size(new_length, max_locals);
		      // Recompute flags since uninitializedThis could have been chopped.
		      flags = 0;
		      for (int i=0; i 0) {
		        locals = new VerificationType[new_length];
		      } else {
		        locals = null;
		      }
		    } else {
		      offset = pre_frame.offset() + offset_delta + 1;
		    }
		    frame = new StackMapFrame(
		      offset, flags, new_length, 0, max_locals, max_stack,
		      locals, null, _verifier);
		    if (first && locals != null) {
		      frame.copy_locals(pre_frame);
		    }
		    return frame;
		  } else if (frame_type < StackMapTable.SAME_EXTENDED + 4) {
		    // append_frame
		    int appends = frame_type - StackMapTable.SAME_EXTENDED;
		    int real_length = pre_frame.locals_size();
		    int new_length = real_length + appends*2;
		    locals = new VerificationType[new_length];
		    VerificationType[] pre_locals = pre_frame.locals();
		    int i;
		    for (i=0; i 0) {
		      locals = new VerificationType[locals_size*2];
		    }
		    int i;
		    for (i=0; i 0) {
		      stack = new VerificationType[stack_size*2];
		    }
		    for (i=0; i max_size)
	      // Since this error could be caused someone rewriting the method
	      // but not knowing to update the stackmap data, we call the the
	      // verifier's error method, which may not throw an exception and
	      // failover to the old verifier instead.
	      throw new VerifierException("StackMapTable format error: bad type array size");
	}

	private VerificationType parse_verification_type(AtomicInteger flags) {
		  int tag = _stream.get_u1();
		  if (tag < VerificationType.ITEM_UninitializedThis) {
		    return VerificationType.from_tag(tag);
		  }
		  if (tag == VerificationType.ITEM_Object) {
		    int class_index = _stream.get_u2();
		    IConstantOperand operand = _verifier.constantWithIndex(class_index);
		    if(!(operand instanceof ClassConstant))
		    	throw new VerifierException("bad class index");
		    return VerificationType.reference_type(((ClassConstant)operand).getClassName().getValue());
		  }
		  if (tag == VerificationType.ITEM_UninitializedThis) {
		    if (flags != null) {
		      flags.set(flags.byteValue() | StackMapFrame.FLAG_THIS_UNINIT);
		    }
		    return VerificationType.uninitialized_this_type;
		  }
		  if (tag == VerificationType.ITEM_Uninitialized) {
		    int offset = _stream.get_u2();
		    if (offset >= _code_length ||
		        _code_data[offset] != ClassVerifier.NEW_OFFSET) {
		      throw new VerifierException("StackMapTable format error: bad offset for Uninitialized");
		    }
		    return VerificationType.uninitialized_type((short)offset);
		  }
		  throw new VerifierException("bad verification type");
		 }

	public void check_end() {
		if(_stream!=null && !_stream.at_end())
			throw new VerifierException("wrong attribute size");
		
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy