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

soot.jimple.toolkits.typing.ConstraintChecker Maven / Gradle / Ivy

There is a newer version: 2.5.0-9
Show newest version
/* Soot - a J*va Optimization Framework
 * Copyright (C) 1997-2000 Etienne Gagnon.  All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

/*
 * Modified by the Sable Research Group and others 1997-1999.  
 * See the 'credits' file distributed with Soot for the complete list of
 * contributors.  (Soot is distributed at http://www.sable.mcgill.ca/soot)
 */


package soot.jimple.toolkits.typing;

import soot.*;
import soot.jimple.*;
import java.util.*;
import java.io.*;

class ConstraintChecker extends AbstractStmtSwitch
{
  private final ClassHierarchy hierarchy;
  private final boolean fix;  // if true, fix constraint violations
  
  private JimpleBody stmtBody;

  public ConstraintChecker(TypeResolver resolver, boolean fix)
  {
    this.fix = fix;

    hierarchy = resolver.hierarchy();
  }

  public void check(Stmt stmt, JimpleBody stmtBody) throws TypeException
  {
    try
      {
	this.stmtBody = stmtBody;
	stmt.apply(this);
      }
    catch(RuntimeTypeException e)
      {
        StringWriter st = new StringWriter();
        PrintWriter pw = new PrintWriter(st);
	e.printStackTrace(pw);
	pw.close();
	throw new TypeException(st.toString());
      }
  }

  private static class RuntimeTypeException extends RuntimeException
  {
    RuntimeTypeException(String message)
    {
      super(message);
    }
  }

  static void error(String message)
  {
    throw new RuntimeTypeException(message);
  }

  private void handleInvokeExpr(InvokeExpr ie, Stmt invokestmt)
  {
    if(ie instanceof InterfaceInvokeExpr)
      {
	InterfaceInvokeExpr invoke = (InterfaceInvokeExpr) ie;
	
	SootMethodRef method = invoke.getMethodRef();
	Value base = invoke.getBase();
	
	if(base instanceof Local)
	  {
	    Local local = (Local) base;
	    
	    if(!hierarchy.typeNode(local.getType()).hasAncestorOrSelf(hierarchy.typeNode(method.declaringClass().getType())))
	      {
		if(fix)
		  {
		    invoke.setBase(insertCast(local, method.declaringClass().getType(), invokestmt));
		  }
		else
		  {
		    error("Type Error(7): local " + local + " is of incompatible type " +  local.getType());
		  }
	      }
	  }
	
	int count = invoke.getArgCount();
	
	for(int i = 0; i < count; i++)
	  {
	    if(invoke.getArg(i) instanceof Local)
	      {
		Local local = (Local) invoke.getArg(i);

		if(!hierarchy.typeNode(local.getType()).hasAncestorOrSelf(hierarchy.typeNode(method.parameterType(i))))
		  {
		    if(fix)
		      {
			invoke.setArg(i, insertCast(local, method.parameterType(i), invokestmt));
		      }
		    else
		      {
			error("Type Error(8)");
		      }
		  }
	      }
	  }
      }
    else if(ie instanceof SpecialInvokeExpr)
      {
	SpecialInvokeExpr invoke = (SpecialInvokeExpr) ie;

	SootMethodRef method = invoke.getMethodRef();
	Value base = invoke.getBase();

	if(base instanceof Local)
	  {
	    Local local = (Local) base;

	    if(!hierarchy.typeNode(local.getType()).hasAncestorOrSelf(hierarchy.typeNode(method.declaringClass().getType())))
	      {
		if(fix)
		  {
		    invoke.setBase(insertCast(local, method.declaringClass().getType(), invokestmt));
		  }
		else
		  {
		    error("Type Error(9)");
		  }
	      }
	  }

	int count = invoke.getArgCount();

	for(int i = 0; i < count; i++)
	  {
	    if(invoke.getArg(i) instanceof Local)
	      {
		Local local = (Local) invoke.getArg(i);

		if(!hierarchy.typeNode(local.getType()).hasAncestorOrSelf(hierarchy.typeNode(method.parameterType(i))))
		  {
		    if(fix)
		      {
			invoke.setArg(i, insertCast(local, method.parameterType(i), invokestmt));
		      }
		    else
		      {
			error("Type Error(10)");
		      }
		  }
	      }
	  }
      }
    else if(ie instanceof VirtualInvokeExpr)
      {
	VirtualInvokeExpr invoke = (VirtualInvokeExpr) ie;

	SootMethodRef method = invoke.getMethodRef();
	Value base = invoke.getBase();

	if(base instanceof Local)
	  {
	    Local local = (Local) base;

	    if(!hierarchy.typeNode(local.getType()).hasAncestorOrSelf(hierarchy.typeNode(method.declaringClass().getType())))
	      {
		if(fix)
		  {
		    invoke.setBase(insertCast(local, method.declaringClass().getType(), invokestmt));
		  }
		else
		  {
		    error("Type Error(13)");
		  }
	      }
	  }

	int count = invoke.getArgCount();

	for(int i = 0; i < count; i++)
	  {
	    if(invoke.getArg(i) instanceof Local)
	      {
		Local local = (Local) invoke.getArg(i);

		if(!hierarchy.typeNode(local.getType()).hasAncestorOrSelf(hierarchy.typeNode(method.parameterType(i))))
		  {
		    if(fix)
		      {
			invoke.setArg(i, insertCast(local, method.parameterType(i), invokestmt));
		      }
		    else
		      {
			error("Type Error(14)");
		      }
		  }
	      }
	  }
      }
    else if(ie instanceof StaticInvokeExpr)
      {
	StaticInvokeExpr invoke = (StaticInvokeExpr) ie;

	SootMethodRef method = invoke.getMethodRef();

	int count = invoke.getArgCount();

	for(int i = 0; i < count; i++)
	  {
	    if(invoke.getArg(i) instanceof Local)
	      {
		Local local = (Local) invoke.getArg(i);

		if(!hierarchy.typeNode(local.getType()).hasAncestorOrSelf(hierarchy.typeNode(method.parameterType(i))))
		  {
		    if(fix)
		      {
			invoke.setArg(i, insertCast(local, method.parameterType(i), invokestmt));
		      }
		    else
		      {
			error("Type Error(15)");
		      }
		  }
	      }
	  }
      }
    else
      {
	throw new RuntimeException("Unhandled invoke expression type: " + ie.getClass());
      }
  }

  public void caseBreakpointStmt(BreakpointStmt stmt)
  {
    // Do nothing
  }

  public void caseInvokeStmt(InvokeStmt stmt)
  {
    handleInvokeExpr(stmt.getInvokeExpr(), stmt);
  }

  public void caseAssignStmt(AssignStmt stmt)
  {
    Value l = stmt.getLeftOp();
    Value r = stmt.getRightOp();

    TypeNode left = null;

    //******** LEFT ********

    if(l instanceof ArrayRef)
      {
	ArrayRef ref = (ArrayRef) l;
	TypeNode base = hierarchy.typeNode(((Local) ref.getBase()).getType());

	if(!base.isArray())
	  {
	    error("Type Error(16)");
	  }

	left = base.element();
	
	Value index = ref.getIndex();
	
	if(index instanceof Local)
	  {
	    if(!hierarchy.typeNode(((Local) index).getType()).hasAncestorOrSelf(hierarchy.typeNode(IntType.v())))
	      {
		error("Type Error(17)");
	      }
	  }
      }
    else if(l instanceof Local)
      {
	try
	  {
	    left = hierarchy.typeNode(((Local) l).getType());
	  }
	catch(InternalTypingException e)
	  {
	    G.v().out.println("untyped local: " + l);
	    throw e;
	  }
      }
    else if(l instanceof InstanceFieldRef)
      {
	InstanceFieldRef ref = (InstanceFieldRef) l;
	
	TypeNode base = hierarchy.typeNode(((Local) ref.getBase()).getType());
	
	if(!base.hasAncestorOrSelf(hierarchy.typeNode(ref.getField().getDeclaringClass().getType())))
	  {
	    if(fix)
	      {
		ref.setBase(insertCast((Local) ref.getBase(), ref.getField().getDeclaringClass().getType(), stmt));
	      }
	    else
	      {
		error("Type Error(18)");
	      }
	  }

	left = hierarchy.typeNode(ref.getField().getType());
      }
    else if(l instanceof StaticFieldRef)
      {
	StaticFieldRef ref = (StaticFieldRef) l;
	left = hierarchy.typeNode(ref.getField().getType());
      }
    else
      {
	throw new RuntimeException("Unhandled assignment left hand side type: " + l.getClass());
      }

    //******** RIGHT ********

    if(r instanceof ArrayRef)
      {
	ArrayRef ref = (ArrayRef) r;
	TypeNode base = hierarchy.typeNode(((Local) ref.getBase()).getType());

	if(!base.isArray())
	  {
	    error("Type Error(19): " + base + " is not an array type");
	  }

	if(base == hierarchy.NULL)
	  {
	    return;
	  }

	if(!left.hasDescendantOrSelf(base.element()))
	  {
	    if(fix)
	      {
		Type lefttype = left.type();
		if(lefttype instanceof ArrayType)
		  {
		    ArrayType atype = (ArrayType) lefttype;
		    ref.setBase(insertCast((Local) ref.getBase(), ArrayType.v(atype.baseType, atype.numDimensions + 1), stmt));
		  }
		else
		  {
		    ref.setBase(insertCast((Local) ref.getBase(), ArrayType.v(lefttype, 1), stmt));
		  }
	      }
	    else
	      {
		error("Type Error(20)");
	      }
	  }

	Value index = ref.getIndex();
	
	if(index instanceof Local)
	{
	  if(!hierarchy.typeNode(((Local) index).getType()).hasAncestorOrSelf(hierarchy.typeNode(IntType.v())))
	    {
	      error("Type Error(21)");
	    }
	}
      }
    else if(r instanceof DoubleConstant)
      {
	if(!left.hasDescendantOrSelf(hierarchy.typeNode(DoubleType.v())))
	  {
	    error("Type Error(22)");
	  }
      }
    else if(r instanceof FloatConstant)
      {
	if(!left.hasDescendantOrSelf(hierarchy.typeNode(FloatType.v())))
	  {
	    error("Type Error(45)");
	  }
      }
    else if(r instanceof IntConstant)
      {
	if(!left.hasDescendantOrSelf(hierarchy.typeNode(IntType.v())))
	  {
	    error("Type Error(23)");
	  }
      }
    else if(r instanceof LongConstant)
      {
	if(!left.hasDescendantOrSelf(hierarchy.typeNode(LongType.v())))
	  {
	    error("Type Error(24)");
	  }
      }
    else if(r instanceof NullConstant)
      {
	if(!left.hasDescendantOrSelf(hierarchy.typeNode(NullType.v())))
	  {
	    error("Type Error(25)");
	  }
      }
    else if(r instanceof StringConstant)
      {
	if(!left.hasDescendantOrSelf(hierarchy.typeNode(RefType.v("java.lang.String"))))
	  {
	    error("Type Error(26)");
	  }
      }
    else if(r instanceof ClassConstant)
      {
	if(!left.hasDescendantOrSelf(hierarchy.typeNode(RefType.v("java.lang.Class"))))
	  {
	    error("Type Error(27)");
	  }
      }
    else if(r instanceof BinopExpr)
      {
	//******** BINOP EXPR ********
	
	BinopExpr be = (BinopExpr) r;

	Value lv = be.getOp1();
	Value rv = be.getOp2();
	
	TypeNode lop;
	TypeNode rop;

	//******** LEFT ********
	if(lv instanceof Local)
	  {
	    lop = hierarchy.typeNode(((Local) lv).getType());
	  }
	else if(lv instanceof DoubleConstant)
	  {
	    lop = hierarchy.typeNode(DoubleType.v());
	  }
	else if(lv instanceof FloatConstant)
	  {
	    lop = hierarchy.typeNode(FloatType.v());
	  }
	else if(lv instanceof IntConstant)
	  {
	    lop = hierarchy.typeNode(IntType.v());
	  }
	else if(lv instanceof LongConstant)
	  {
	    lop = hierarchy.typeNode(LongType.v());
	  }
	else if(lv instanceof NullConstant)
	  {
	    lop = hierarchy.typeNode(NullType.v());
	  }
	else if(lv instanceof StringConstant)
	  {
	    lop = hierarchy.typeNode(RefType.v("java.lang.String"));
	  }
	else if(lv instanceof ClassConstant)
	  {
	    lop = hierarchy.typeNode(RefType.v("java.lang.Class"));
	  }
	else
	  {
	    throw new RuntimeException("Unhandled binary expression left operand type: " + lv.getClass());
	  }
	
	//******** RIGHT ********
	if(rv instanceof Local)
	  {
	    rop = hierarchy.typeNode(((Local) rv).getType());
	  }
	else if(rv instanceof DoubleConstant)
	  {
	    rop = hierarchy.typeNode(DoubleType.v());
	  }
	else if(rv instanceof FloatConstant)
	  {
	    rop = hierarchy.typeNode(FloatType.v());
	  }
	else if(rv instanceof IntConstant)
	  {
	    rop = hierarchy.typeNode(IntType.v());
	  }
	else if(rv instanceof LongConstant)
	  {
	    rop = hierarchy.typeNode(LongType.v());
	  }
	else if(rv instanceof NullConstant)
	  {
	    rop = hierarchy.typeNode(NullType.v());
	  }
	else if(rv instanceof StringConstant)
	  {
	    rop = hierarchy.typeNode(RefType.v("java.lang.String"));
	  }
	else if(rv instanceof ClassConstant)
	  {
	    rop = hierarchy.typeNode(RefType.v("java.lang.Class"));
	  }
	else
	  {
	    throw new RuntimeException("Unhandled binary expression right operand type: " + rv.getClass());
	  }
	
	if((be instanceof AddExpr) ||
	   (be instanceof SubExpr) ||
	   (be instanceof MulExpr) ||
	   (be instanceof DivExpr) ||
	   (be instanceof RemExpr) ||
	   (be instanceof AndExpr) ||
	   (be instanceof OrExpr) ||
	   (be instanceof XorExpr))
	  {
	    if(!(left.hasDescendantOrSelf(lop) && 
		 left.hasDescendantOrSelf(rop)))
	      {
		error("Type Error(27)");
	      }
	  }
	else if((be instanceof ShlExpr) ||
		(be instanceof ShrExpr) ||
		(be instanceof UshrExpr))
	  {
	    if(!(left.hasDescendantOrSelf(lop) && 
		 hierarchy.typeNode(IntType.v()).hasAncestorOrSelf(rop)))
	      {
		error("Type Error(28)");
	      }
	  }
	else if((be instanceof CmpExpr) ||
		(be instanceof CmpgExpr) ||
		(be instanceof CmplExpr) ||
		(be instanceof EqExpr) ||
		(be instanceof GeExpr) ||
		(be instanceof GtExpr) ||
		(be instanceof LeExpr) ||
		(be instanceof LtExpr) ||
		(be instanceof NeExpr))
	  {
	    try
	      {
		lop.lca(rop);
	      }
	    catch(TypeException e)
	      {
		error(e.getMessage());
	      }

	    if(!left.hasDescendantOrSelf(hierarchy.typeNode(IntType.v())))
	      {
		error("Type Error(29)");
	      }
	  }
	else
	  {
	    throw new RuntimeException("Unhandled binary expression type: " + be.getClass());
	  }
      }
    else if(r instanceof CastExpr)
      {
	CastExpr ce = (CastExpr) r;
	TypeNode cast = hierarchy.typeNode(ce.getCastType());
	if(ce.getOp() instanceof Local)
	{
	  TypeNode op = hierarchy.typeNode(((Local) ce.getOp()).getType());

	  try
	    {
	      // we must be careful not to reject primitive type casts (e.g. int to long)
	      if(cast.isClassOrInterface() || op.isClassOrInterface())
	        {
		  cast.lca(op);
	        }
	    }
	  catch(TypeException e)
	    {
	      G.v().out.println(r + "[" + op + "<->" + cast + "]");
	      error(e.getMessage());
	    }
	}

	if(!left.hasDescendantOrSelf(cast))
	  {
	    error("Type Error(30)");
	  }
      }
    else if(r instanceof InstanceOfExpr)
      {
	InstanceOfExpr ioe = (InstanceOfExpr) r;
	TypeNode type = hierarchy.typeNode(ioe.getCheckType());
	TypeNode op = hierarchy.typeNode(ioe.getOp().getType());
	
	try
	  {
	    op.lca(type);
	  }
	catch(TypeException e)
	  {
	    G.v().out.println(r + "[" + op + "<->" + type + "]");
	    error(e.getMessage());
	  }
	
	if(!left.hasDescendantOrSelf(hierarchy.typeNode(IntType.v())))
	  {
	    error("Type Error(31)");
	  }
      }
    else if(r instanceof InvokeExpr)
      {
	InvokeExpr ie = (InvokeExpr) r;

	handleInvokeExpr(ie, stmt);

	if(!left.hasDescendantOrSelf(hierarchy.typeNode(ie.getMethodRef().returnType())))
	  {
	    error("Type Error(32)");
	  }
      }
    else if(r instanceof NewArrayExpr)
      {
	NewArrayExpr nae = (NewArrayExpr) r;

	Type baseType = nae.getBaseType();
	TypeNode right;

	if(baseType instanceof ArrayType)
	  {
	    right = hierarchy.typeNode(ArrayType.v(((ArrayType) baseType).baseType, 
						      ((ArrayType) baseType).numDimensions + 1));
	  }
	else
	  {
	    right = hierarchy.typeNode(ArrayType.v(baseType, 1));
	  }

	if(!left.hasDescendantOrSelf(right))
	  {
	    error("Type Error(33)");
	  }


	Value size = nae.getSize();
	if(size instanceof Local)
	  {
	    TypeNode var = hierarchy.typeNode(((Local) size).getType());

	    if(!var.hasAncestorOrSelf(hierarchy.typeNode(IntType.v())))
	      {
		error("Type Error(34)");
	      }
	  }
      }
    else if(r instanceof NewExpr)
      {
	NewExpr ne = (NewExpr) r;

	if(!left.hasDescendantOrSelf(hierarchy.typeNode(ne.getBaseType())))
	  {
	    error("Type Error(35)");
	  }
      }
    else if(r instanceof NewMultiArrayExpr)
      {
	NewMultiArrayExpr nmae = (NewMultiArrayExpr) r;

	if(!left.hasDescendantOrSelf(hierarchy.typeNode(nmae.getBaseType())))
	  {
	    error("Type Error(36)");
	  }

	for(int i = 0; i < nmae.getSizeCount(); i++)
	  {
	    Value size = nmae.getSize(i);
	    if(size instanceof Local)
	      {
		TypeNode var = hierarchy.typeNode(((Local) size).getType());

		if(!var.hasAncestorOrSelf(hierarchy.typeNode(IntType.v())))
		  {
		    error("Type Error(37)");
		  }
	      }
	  }
      }
    else if(r instanceof LengthExpr)
      {
	LengthExpr le = (LengthExpr) r;

	if(!left.hasDescendantOrSelf(hierarchy.typeNode(IntType.v())))
	  {
	    error("Type Error(38)");
	  }

	if(le.getOp() instanceof Local)
	  {
	    if(!hierarchy.typeNode(((Local) le.getOp()).getType()).isArray())
	      {
		error("Type Error(39)");
	      }
	  }
      }
    else if(r instanceof NegExpr)
      {
	NegExpr ne = (NegExpr) r;
	TypeNode right;

	if(ne.getOp() instanceof Local)
	  {
	    right = hierarchy.typeNode(((Local) ne.getOp()).getType());
	  }
	else if(ne.getOp() instanceof DoubleConstant)
	  {
	    right = hierarchy.typeNode(DoubleType.v());
	  }
	else if(ne.getOp() instanceof FloatConstant)
	  {
	    right = hierarchy.typeNode(FloatType.v());
	  }
	else if(ne.getOp() instanceof IntConstant)
	  {
	    right = hierarchy.typeNode(IntType.v());
	  }
	else if(ne.getOp() instanceof LongConstant)
	  {
	    right = hierarchy.typeNode(LongType.v());
	  }
	else
	  {
	    throw new RuntimeException("Unhandled neg expression operand type: " + ne.getOp().getClass());
	  }
	
	if(!left.hasDescendantOrSelf(right))
	  {
	    error("Type Error(40)");
	  }
      }
    else if(r instanceof Local)
      {
	if(!left.hasDescendantOrSelf(hierarchy.typeNode(((Local) r).getType())))
	  {
	    if(fix)
	      {
		stmt.setRightOp(insertCast((Local) r, left.type(), stmt));
	      }
	    else
	      {
		error("Type Error(41)");
	      }
	  }
      }
    else if(r instanceof InstanceFieldRef)
      {
	InstanceFieldRef ref = (InstanceFieldRef) r;

	TypeNode baseType = hierarchy.typeNode(((Local) ref.getBase()).getType());
	if(!baseType.hasAncestorOrSelf(hierarchy.typeNode(ref.getField().getDeclaringClass().getType())))
	  {
	    if(fix)
	      {
		ref.setBase(insertCast((Local) ref.getBase(), ref.getField().getDeclaringClass().getType(), stmt));
	      }
	    else
	      {
		error("Type Error(42)");
	      }	    
	  }
	
	if(!left.hasDescendantOrSelf(hierarchy.typeNode(ref.getField().getType())))
	  {
	    error("Type Error(43)");
	  }
      }
    else if(r instanceof StaticFieldRef)
      {
	StaticFieldRef ref = (StaticFieldRef) r;

	if(!left.hasDescendantOrSelf(hierarchy.typeNode(ref.getField().getType())))
	  {
	    error("Type Error(44)");
	  }
      }
    else
      {
	throw new RuntimeException("Unhandled assignment right hand side type: " + r.getClass());
      }
  }

  public void caseIdentityStmt(IdentityStmt stmt)
  {
    TypeNode left = hierarchy.typeNode(((Local) stmt.getLeftOp()).getType());

    Value r = stmt.getRightOp();

    if(!(r instanceof CaughtExceptionRef))
      {
	TypeNode right = hierarchy.typeNode(r.getType());
	if(!left.hasDescendantOrSelf(right))
	  {
	    error("Type Error(46) [" + left + " <- " + right + "]");
	  }
      }
    else
      {
	List exceptionTypes = TrapManager.getExceptionTypesOf(stmt, stmtBody);
	Iterator typeIt = exceptionTypes.iterator();
	
	while(typeIt.hasNext())
	  {
	    Type t = (Type) typeIt.next();
	    
	    if(!left.hasDescendantOrSelf(hierarchy.typeNode(t)))
	      {
		error("Type Error(47)");
	      }
	  }
	
	if(!left.hasAncestorOrSelf(hierarchy.typeNode(RefType.v("java.lang.Throwable"))))
	  {
	    error("Type Error(48)");
	  }
      }
  }

  public void caseEnterMonitorStmt(EnterMonitorStmt stmt)
  {
    if(stmt.getOp() instanceof Local)
      {
	TypeNode op = hierarchy.typeNode(((Local) stmt.getOp()).getType());
	
	if(!op.hasAncestorOrSelf(hierarchy.typeNode(RefType.v("java.lang.Object"))))
	  {
	    error("Type Error(49)");
	  }    
      }
  }

  public void caseExitMonitorStmt(ExitMonitorStmt stmt)
  {
    if(stmt.getOp() instanceof Local)
      {
	TypeNode op = hierarchy.typeNode(((Local) stmt.getOp()).getType());
	
	if(!op.hasAncestorOrSelf(hierarchy.typeNode(RefType.v("java.lang.Object"))))
	  {
	    error("Type Error(49)");
	  }    
      }
  }

  public void caseGotoStmt(GotoStmt stmt)
  {
  }

  public void caseIfStmt(IfStmt stmt)
  {
    ConditionExpr cond = (ConditionExpr) stmt.getCondition();
    
    BinopExpr expr = cond;
    Value lv = expr.getOp1();
    Value rv = expr.getOp2();
    
    TypeNode lop;
    TypeNode rop;
    
    //******** LEFT ********
    if(lv instanceof Local)
      {
	lop = hierarchy.typeNode(((Local) lv).getType());
      }
    else if(lv instanceof DoubleConstant)
      {
	lop = hierarchy.typeNode(DoubleType.v());
      }
    else if(lv instanceof FloatConstant)
      {
	lop = hierarchy.typeNode(FloatType.v());
      }
    else if(lv instanceof IntConstant)
      {
	lop = hierarchy.typeNode(IntType.v());
      }
    else if(lv instanceof LongConstant)
      {
	lop = hierarchy.typeNode(LongType.v());
      }
    else if(lv instanceof NullConstant)
      {
	lop = hierarchy.typeNode(NullType.v());
      }
    else if(lv instanceof StringConstant)
      {
	lop = hierarchy.typeNode(RefType.v("java.lang.String"));
      }
    else if(lv instanceof ClassConstant)
      {
	lop = hierarchy.typeNode(RefType.v("java.lang.Class"));
      }
    else
      {
	throw new RuntimeException("Unhandled binary expression left operand type: " + lv.getClass());
      }
    
    //******** RIGHT ********
    if(rv instanceof Local)
      {
	rop = hierarchy.typeNode(((Local) rv).getType());
      }
    else if(rv instanceof DoubleConstant)
      {
	rop = hierarchy.typeNode(DoubleType.v());
      }
    else if(rv instanceof FloatConstant)
      {
	rop = hierarchy.typeNode(FloatType.v());
	  }
    else if(rv instanceof IntConstant)
      {
	rop = hierarchy.typeNode(IntType.v());
      }
    else if(rv instanceof LongConstant)
      {
	rop = hierarchy.typeNode(LongType.v());
      }
    else if(rv instanceof NullConstant)
      {
	rop = hierarchy.typeNode(NullType.v());
      }
    else if(rv instanceof StringConstant)
      {
	rop = hierarchy.typeNode(RefType.v("java.lang.String"));
      }
    else if(rv instanceof ClassConstant)
      {
	rop = hierarchy.typeNode(RefType.v("java.lang.Class"));
      }
    else
      {
	throw new RuntimeException("Unhandled binary expression right operand type: " + rv.getClass());
      }
    
    try
      {
	lop.lca(rop);
      }
    catch(TypeException e)
      {
	error(e.getMessage());
      }
  }

  public void caseLookupSwitchStmt(LookupSwitchStmt stmt)
  {
    Value key = stmt.getKey();

    if(key instanceof Local)
      {
	if(!hierarchy.typeNode(((Local) key).getType()).hasAncestorOrSelf(hierarchy.typeNode(IntType.v())))
	  {
	    error("Type Error(50)");
	  }
      }
  }

  public void caseNopStmt(NopStmt stmt)
  {
  }

  public void caseReturnStmt(ReturnStmt stmt)
  {
    if(stmt.getOp() instanceof Local)
      {
	if(!hierarchy.typeNode(((Local) stmt.getOp()).getType()).
	   hasAncestorOrSelf(hierarchy.typeNode(stmtBody.getMethod().getReturnType())))
	  {
	    if(fix)
	      {
		stmt.setOp(insertCast((Local) stmt.getOp(), stmtBody.getMethod().getReturnType(), stmt));
	      }
	    else
	      {
		error("Type Error(51)");
	      }
	  }
      }
  }

  public void caseReturnVoidStmt(ReturnVoidStmt stmt)
  {
  }

  public void caseTableSwitchStmt(TableSwitchStmt stmt)
  {
    Value key = stmt.getKey();

    if(key instanceof Local)
      {
	if(!hierarchy.typeNode(((Local) key).getType()).hasAncestorOrSelf(hierarchy.typeNode(IntType.v())))
	  {
	    error("Type Error(52)");
	  }
      }
  }

  public void caseThrowStmt(ThrowStmt stmt)
  {
    if(stmt.getOp() instanceof Local)
      {
	TypeNode op = hierarchy.typeNode(((Local) stmt.getOp()).getType());
	    
	if(!op.hasAncestorOrSelf(hierarchy.typeNode(RefType.v("java.lang.Throwable"))))
	  {
	    if(fix)
	      {
		stmt.setOp(insertCast((Local) stmt.getOp(), RefType.v("java.lang.Throwable"), stmt));
	      }
	    else
	      {
		error("Type Error(53)");
	      }
	  }
      }
  }

  public void defaultCase(Stmt stmt)
  {
    throw new RuntimeException("Unhandled statement type: " + stmt.getClass());
  }

  private Local insertCast(Local oldlocal, Type type, Stmt stmt)
  {
    Local newlocal = Jimple.v().newLocal("tmp", type);
    stmtBody.getLocals().add(newlocal);
    
    stmtBody.getUnits().insertBefore(Jimple.v().newAssignStmt(newlocal, Jimple.v().newCastExpr(oldlocal, type)), stmt);
    return newlocal;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy