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

soot.jimple.toolkits.annotation.arraycheck.ArrayBoundsChecker Maven / Gradle / Ivy

There is a newer version: 1.12.0
Show newest version
/* Soot - a J*va Optimization Framework
 * Copyright (C) 2000 Feng Qian
 *
 * 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.annotation.arraycheck;
import soot.options.*;

import soot.*;
import soot.jimple.*;
import soot.util.*;
import soot.tagkit.*;
import soot.jimple.toolkits.annotation.tags.*;
import java.util.*;
import soot.options.ABCOptions;

public class ArrayBoundsChecker extends BodyTransformer
{
    public ArrayBoundsChecker( Singletons.Global g ) {}
    public static ArrayBoundsChecker v() { return G.v().soot_jimple_toolkits_annotation_arraycheck_ArrayBoundsChecker(); }

    protected boolean takeClassField = false;
    protected boolean takeFieldRef = false;
    protected boolean takeArrayRef = false;
    protected boolean takeCSE = false;
    protected boolean takeRectArray = false;
    protected boolean addColorTags = false;
    
    protected void internalTransform(Body body, String phaseName, Map opts)
    {
        ABCOptions options = new ABCOptions( opts );
        if (options.with_all())
        {
            takeClassField = true;
            takeFieldRef = true;
            takeArrayRef = true;
            takeCSE = true;
            takeRectArray = true;
        }
        else
        {
            takeClassField = options.with_classfield();
            takeFieldRef = options.with_fieldref();
            takeArrayRef = options.with_arrayref();
            takeCSE = options.with_cse();
            takeRectArray = options.with_rectarray();
        }

        addColorTags = options.add_color_tags();

        {
            SootMethod m = body.getMethod();
        
            Date start = new Date();

            if (Options.v().verbose())
            {
                G.v().out.println("[abc] Analyzing array bounds information for "+m.getName());
                G.v().out.println("[abc] Started on "+start);
            }

            ArrayBoundsCheckerAnalysis analysis = null;

            if (hasArrayLocals(body))
            {
                analysis = 
                    new ArrayBoundsCheckerAnalysis(body, 
                                                   takeClassField, 
                                                   takeFieldRef, 
                                                   takeArrayRef, 
                                                   takeCSE, 
                                                   takeRectArray);
            }
            
            SootClass counterClass = null;
            SootMethod increase = null;
            
            if (options.profiling())
            {
                counterClass = Scene.v().loadClassAndSupport("MultiCounter");
                increase = counterClass.getMethod("void increase(int)") ;
            }
            
            Chain units = body.getUnits();
            
            IntContainer zero = new IntContainer(0);
            
            Iterator unitIt = units.snapshotIterator();
            
            /*
             * RoboVM note: Added "analysis != null" here to prevent an NPE
             * inside this loop if analysis == null. This fixes issue #275.
             */
            while (analysis != null && unitIt.hasNext())
            {
                Stmt stmt = (Stmt)unitIt.next();
	   
                if (stmt.containsArrayRef())
                {
                    ArrayRef aref = stmt.getArrayRef();
                    
                    {
                        WeightedDirectedSparseGraph vgraph = 
                            (WeightedDirectedSparseGraph)analysis.getFlowBefore(stmt);
            
                        int res = interpretGraph(vgraph, aref, stmt, zero);
                        
                        boolean lowercheck = true;
                        boolean uppercheck = true;
                        
                        if (res == 0) {
                            lowercheck = true;
                            uppercheck = true;
                        }
                        else if (res == 1) {
                            lowercheck = true;
                            uppercheck = false;
                        }
                        else if (res == 2) {
                            lowercheck = false;
                            uppercheck = true;
                        }
                        else if (res == 3) {
                            lowercheck = false;
                            uppercheck = false;
                        }
               
                        if (addColorTags){
                            if (res == 0) {
                                aref.getIndexBox().addTag(new ColorTag(255, 0, 0, false, "ArrayCheckTag"));
                            }
                            else if (res == 1) {
                                aref.getIndexBox().addTag(new ColorTag(255, 248, 35, false, "ArrayCheckTag"));
                            }
                            else if (res == 2) {
                                aref.getIndexBox().addTag(new ColorTag(255, 163, 0, false, "ArrayCheckTag"));
                            }
                            else if (res == 3) {
                                aref.getIndexBox().addTag(new ColorTag(45, 255, 84, false, "ArrayCheckTag"));
                            }
                            SootClass bodyClass = body.getMethod().getDeclaringClass();
                            Iterator keysIt = bodyClass.getTags().iterator();
                            boolean keysAdded = false;
                            while (keysIt.hasNext()){
                                Object next = keysIt.next();
                                if (next instanceof KeyTag){
                                    if (((KeyTag)next).analysisType().equals("ArrayCheckTag")){
                                        keysAdded = true;
                                    }
                                }
                            }
                            if (!keysAdded){
                                bodyClass.addTag(new KeyTag(255, 0, 0, "ArrayBounds: Unsafe Lower and Unsafe Upper", "ArrayCheckTag"));
                                bodyClass.addTag(new KeyTag(255, 248, 35, "ArrayBounds: Unsafe Lower and Safe Upper", "ArrayCheckTag"));
                                bodyClass.addTag(new KeyTag(255, 163, 0, "ArrayBounds: Safe Lower and Unsafe Upper", "ArrayCheckTag"));
                                bodyClass.addTag(new KeyTag(45, 255, 84, "ArrayBounds: Safe Lower and Safe Upper", "ArrayCheckTag"));
                            }
                        }

                        /*
                        boolean lowercheck = true;
                        boolean uppercheck = true;
                        
                        {
                            if (Options.v().debug())
                            {
                                if (!vgraph.makeShortestPathGraph())
                                {
                                    G.v().out.println(stmt+" :");
                                    G.v().out.println(vgraph);
                                }
                            }
                            
                            Value base = aref.getBase();
                            Value index = aref.getIndex();
                            
                            if (index instanceof IntConstant)
                            {
                                int indexv = ((IntConstant)index).value;
                                
                                if (vgraph.hasEdge(base, zero))
                                {
                                    int alength = vgraph.edgeWeight(base, zero);
                                    
                                    if (-alength > indexv)
                                        uppercheck = false;
                                }
                                
                                if (indexv >= 0)
                                    lowercheck = false;			
                            }
                            else
                            {
                                if (vgraph.hasEdge(base, index))
                                {
                                    int upperdistance = vgraph.edgeWeight(base, index);
                                    if (upperdistance < 0)
                                        uppercheck = false;
                                }
                                
                                if (vgraph.hasEdge(index, zero))
                                {
                                    int lowerdistance = vgraph.edgeWeight(index, zero);

                                    if (lowerdistance <= 0)
                                        lowercheck = false;
                                }
                            }
                        }*/
                        
                        if (options.profiling())
                        {
                            int lowercounter = 0;
                            if (!lowercheck)
                                lowercounter = 1;
                            
                            units.insertBefore (Jimple.v().newInvokeStmt( 
                                 Jimple.v().newStaticInvokeExpr(increase.makeRef(), 
                                        IntConstant.v(lowercounter))), stmt);

                            int uppercounter = 2;
                            if (!uppercheck)
                                uppercounter = 3;
                            
                            units.insertBefore (Jimple.v().newInvokeStmt( 
                                 Jimple.v().newStaticInvokeExpr(increase.makeRef(), 
                                        IntConstant.v(uppercounter))), stmt) ;

                            /*
                            if (!lowercheck && !uppercheck)
                            {
                                units.insertBefore(Jimple.v().newInvokeStmt(
                                  Jimple.v().newStaticInvokeExpr(increase,
                                        IntConstant.v(4))), stmt);

                                NullCheckTag nullTag = (NullCheckTag)stmt.getTag("NullCheckTag");
			    
                                if (nullTag != null && !nullTag.needCheck())
                                    units.insertBefore(Jimple.v().newInvokeStmt(
                                        Jimple.v().newStaticInvokeExpr(increase,
                                            IntConstant.v(7))), stmt);
                            }
                            */
                        }
                        else
                        {
                            Tag checkTag = new ArrayCheckTag(lowercheck, uppercheck);
                            stmt.addTag(checkTag);
                        }
                    }
                }
            }

            if( addColorTags && takeRectArray ) {
                RectangularArrayFinder raf = RectangularArrayFinder.v();
                for( Iterator vbIt = body.getUseAndDefBoxes().iterator(); vbIt.hasNext(); ) {
                    final ValueBox vb = (ValueBox) vbIt.next();
                    Value v = vb.getValue();
                    if( !(v instanceof Local) ) continue;
                    Type t = v.getType();
                    if( !(t instanceof ArrayType) ) continue;
                    ArrayType at = (ArrayType) t;
                    if( at.numDimensions <= 1 ) continue;
                    vb.addTag( new ColorTag(
                        raf.isRectangular( new MethodLocal(m, (Local) v) )
                                   ? ColorTag.GREEN
                                   : ColorTag.RED ));
                }
            }

            Date finish = new Date();
            if (Options.v().verbose()) 
            {
                long runtime = finish.getTime() - start.getTime();
                G.v().out.println("[abc] ended on "+finish
                                  +". It took "+(runtime/60000)+" min. "
                                  +((runtime%60000)/1000)+" sec.");
            }
        }
    }

    private boolean hasArrayLocals(Body body)
    {
        Iterator localIt = body.getLocals().iterator();
        
        while (localIt.hasNext())
        {
            Local local = (Local)localIt.next();
            if (local.getType() instanceof ArrayType)
                return true;
        }
        
        return false;
    }

    protected int interpretGraph(WeightedDirectedSparseGraph vgraph, ArrayRef aref, Stmt stmt, IntContainer zero){
    
        boolean lowercheck = true;
        boolean uppercheck = true;
                        
        {
            if (Options.v().debug())
            {
                if (!vgraph.makeShortestPathGraph())
                {
                    G.v().out.println(stmt+" :");
                    G.v().out.println(vgraph);
                }
            }
                            
            Value base = aref.getBase();
            Value index = aref.getIndex();
                            
            if (index instanceof IntConstant)
            {
                int indexv = ((IntConstant)index).value;
                        
                if (vgraph.hasEdge(base, zero))
                {
                    int alength = vgraph.edgeWeight(base, zero);
                                    
                    if (-alength > indexv)
                        uppercheck = false;
                }
                                
                if (indexv >= 0)
                    lowercheck = false;			
            }
            else
            {
                if (vgraph.hasEdge(base, index))
                {
                    int upperdistance = vgraph.edgeWeight(base, index);
                    if (upperdistance < 0)
                        uppercheck = false;
                }
                                
                if (vgraph.hasEdge(index, zero))
                {
                    int lowerdistance = vgraph.edgeWeight(index, zero);

                    if (lowerdistance <= 0)
                        lowercheck = false;
                }
            }
        }
                        
        
        if (lowercheck && uppercheck) return 0;
        else if (lowercheck && !uppercheck) return 1;
        else if (!lowercheck && uppercheck) return 2;
        else return 3;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy