package fr.lifl.stc.stan.analyser; //import java.util.Vector; import java.io.IOException; import gnu.getopt.Getopt; import gnu.getopt.LongOpt; import org.apache.bcel.classfile.ClassParser; import org.apache.bcel.classfile.JavaClass; import org.antlr.runtime.RecognitionException; import fr.lifl.stc.stan.classAnnoter.LinkMapClassAnnoter; import fr.lifl.stc.stan.implicitFlow.QuineMcCluskey.Minimization; import fr.lifl.stc.stan.link.LinkFactory; import fr.lifl.stc.stan.link.TableLink; import fr.lifl.stc.stan.link.defaultLink.DefaultLinkFactory; import fr.lifl.stc.stan.policy.Policy; import fr.lifl.stc.stan.policy.defaultPolicy.DefaultPolicy; import fr.lifl.stc.stan.signature.SignatureDictionary; import fr.lifl.stc.stan.tools.HTMLOutput; import fr.lifl.stc.stan.tools.NativesAnnoter; import fr.lifl.stc.stan.util.Printer; import fr.lifl.stc.stan.dsl.DSLReader; import fr.lifl.stc.stan.dsl.PolicyManager; import fr.lifl.stc.stan.dsl.FlowChecker; /** * @author Julien Graziano * @author Dorina */ public class GlobalAnalyser { private SignatureDictionary dictionary; private Policy policy; private FlowChecker flowchecker; /** Checker for dsl policies */ private JavaClass classes[]; public static LinkFactory linkFactory = new DefaultLinkFactory(); /** * Creates a new GlobalAnalyser instance. * * @param classes * set of classfiles to analyse * @throws ClassNotFoundException * @throws IOException * */ public GlobalAnalyser(JavaClass[] classes) throws IOException, ClassNotFoundException { /** * loading dictionary */ System.out.println("[init] Loading dictionary "+Config.getDictionary()); dictionary = new SignatureDictionary(Config.getDictionary()); /** * adds initial dictionary (e.g. api dictionary) content to main dictionary */ if (Config.getInitialDictionary() != null) { System.out.println("[init] Adding initial dictionary "+Config.getInitialDictionary()); dictionary.addContent(Config.getInitialDictionary()); } /** * loads policy file */ if(Config.getPolicy()!=null) { System.out.println("[init] Loading policy file "+Config.getPolicy()); policy = new DefaultPolicy(Config.getPolicy()); } else{ policy = new DefaultPolicy(); } /** * loads DSL policies file */ if(Config.getDSLFile()!=null) { System.out.println("[init] Loading DSL policies file "+Config.getDSLFile()); DSLReader dsl=null; try { dsl = new DSLReader(Config.getDSLFile()); } catch(RecognitionException e) { System.out.println("[init] There was an error reading the DSL file, ignoring it : " + e.getMessage()); } catch(IOException e) { System.out.println("[init] There was an error while trying to open DSL file, ignoring it : " + e.getMessage()); } if ( dsl == null ) flowchecker = new FlowChecker(new PolicyManager()); else flowchecker = new FlowChecker(dsl.policies); } else{ flowchecker = new FlowChecker(new PolicyManager()); } /** * creates the class hierarchy */ System.out.println("[init] Register classes"); System.out.println("no of classes "+classes.length); //Printer.println("no of classes "+classes.length); for (int i = 0; i < classes.length; i++) { policy.registerClass(classes[i]); dictionary.registerClass(classes[i]); } /** * registers methods in the class hierarchy */ System.out.println("[init] Register methods"); for (int i = 0; i < classes.length; i++) { dictionary.registerMethods(classes[i]); } /** * registers manual annotations */ if(Config.getHandAnnotationsFile()!=null) { System.out.println("[init] Add hand-annotations"); NativesAnnoter na = new NativesAnnoter(dictionary, Config.getHandAnnotationsFile(), classes); na.addToDico(); } this.classes = classes; } /** * @see fr.lifl.stc.stan.analyser.Analyser#analyse() Analyse le * groupe de classes par passes successives tant qu'un changement * apparait dans le dictionnaire */ public void analyse() throws IOException { ClassAnalyser canalyser; int noCycles = 0; do { Stats.initIteration(); StatsEscape.init(); System.out.println("\n\n[run] START cycle "+noCycles+"\n"); //Printer.println("\n\n[run] START cycle "+noCycles+"\n"); dictionary.setUnChanged(); for (int i = 0; i < classes.length; i++) { Printer.println("\n[run] Analysing class "+ classes[i].getFileName()); HTMLOutput.openHTMLOutput(Config.htmlRep() + classes[i].getClassName()); canalyser = new ClassAnalyser(dictionary, policy, flowchecker, classes[i]); canalyser.analyse(); HTMLOutput.closeHTMLOutput(); } Stats.endIteration(); noCycles++; } while (dictionary.isChanged()); /** * writes dictionary to file */ dictionary.dump(); /** * prints statistics */ System.out.println("noCycles:\t" + noCycles); if (Config.statisticsEnabled()) { Stats.println("noCycles:\t" + noCycles +" \n ProofSize:\t" + Stats.sizeOfProof + "\n max table link L = " + TableLink.maxL + "\n max table link C = " + TableLink.maxC); Stats.printStats(); StatsEscape.print(); } if (Config.implicitFlowEnabled()) { Minimization.stats.printStats(); } // annotated classes with signatures if (Config.annotateEnabled()) this.annotate(); } /** * annotates classes with link map attribute * @throws IOException */ private void annotate() throws IOException { for (int i = 0; i < classes.length; i++) { LinkMapClassAnnoter la = new LinkMapClassAnnoter(classes[i], dictionary); la.annotateClass(); } } /** * prints help * */ private static void printHelp() { System.out.println("Usage : if_analyze "); System.out.println("where possible options include: "); System.out.println(" -h/--help : print this help"); System.out.println(" -v/--verbose : verbose mode"); System.out.println(" -d/--dictionary : use as dictionary"); System.out.println(" -p/--path : use as path for files below"); System.out.println(" -i/--initial-dictionary : use as initial dictionary (for hand annotations)"); System.out.println(" -H/--hand-annotations : use as file containing hand written annotations"); System.out.println(" -P/--policy : use as file policy (e.g. containing secret attributes)"); System.out.println(" -a/--annotate : annotate the .class files "); System.out.println(" -r/--annotate-rep : use as a basis for annotated class dumps"); System.out.println(" -s/--statistics : produce statistics"); System.out.println(" -o/--statistics-file : use as statistics output"); System.out.println(" -t/--html : produce html dumps"); System.out.println(" -b/--html-rep : use as a basis for html dumps"); System.out.println(" -c/--configuration : use configuration from config.xml"); System.out.println(" -w/--worst-signature : use the worst signature as global signature for abstract methods"); System.out.println(" -x/--directory : analyze all .class files in and its subdirectories"); System.out.println(" -f/--file : analyze all .class in file"); } /** * Loads, from bcel, classes passed as line arguments and launches the * analyzer */ public static void main(String args[]) { int error, i; long time1, time2; GlobalAnalyser ganalyser; JavaClass classes[]; time1 = System.currentTimeMillis(); error = i = 0; int c; LongOpt[] longopts = new LongOpt[16]; longopts[0] = new LongOpt("help", LongOpt.NO_ARGUMENT, null, 'h'); longopts[1] = new LongOpt("dictionary", LongOpt.REQUIRED_ARGUMENT, null, 'd'); longopts[2] = new LongOpt("initial-dictionary", LongOpt.REQUIRED_ARGUMENT, null, 'i'); longopts[3] = new LongOpt("policy", LongOpt.REQUIRED_ARGUMENT, null, 'P'); longopts[4] = new LongOpt("annotate", LongOpt.NO_ARGUMENT, null, 'a'); longopts[5] = new LongOpt("annotate-rep", LongOpt.REQUIRED_ARGUMENT, null, 'r'); longopts[6] = new LongOpt("statistics", LongOpt.NO_ARGUMENT, null, 's'); longopts[7] = new LongOpt("statistics-file", LongOpt.REQUIRED_ARGUMENT, null, 'o'); longopts[8] = new LongOpt("html", LongOpt.NO_ARGUMENT, null, 't'); longopts[9] = new LongOpt("html-rep", LongOpt.REQUIRED_ARGUMENT, null, 'b'); longopts[10] = new LongOpt("configuration", LongOpt.REQUIRED_ARGUMENT, null, 'c'); longopts[11] = new LongOpt("worst-signature", LongOpt.NO_ARGUMENT, null, 'w'); longopts[12] = new LongOpt("verbose", LongOpt.NO_ARGUMENT, null, 'v'); longopts[13] = new LongOpt("path", LongOpt.REQUIRED_ARGUMENT, null, 'p'); longopts[14] = new LongOpt("hand-annotations", LongOpt.REQUIRED_ARGUMENT, null, 'H'); longopts[15] = new LongOpt("file", LongOpt.REQUIRED_ARGUMENT, null, 'f'); Getopt g = new Getopt("GlobalAnalyzer", args, "hvp:d:i:H:P:ar:so:tb:c:f:wvW;", longopts); try { while ((c = g.getopt()) != -1) { switch (c) { case 'h': printHelp(); System.exit(0); break; case 'v': Config.setEnableVerbose(true); break; case 'p': Config.setPath(g.getOptarg()); break; case 'c': Config.loadXMLConfigFile(g.getOptarg()); break; case 'd': Config.setDictionary(g.getOptarg()); break; case 'i': Config.setInitialDictionary(g.getOptarg()); break; case 'P': Config.setPolicy(g.getOptarg()); break; case 'H': Config.setHandAnnotationsFile(g.getOptarg()); break; case 'a': Config.setEnableAnnotate(true); break; case 'r': Config.setAnnotationRep(g.getOptarg()); break; case 's': Config.setEnableStatistics(true); break; case 'o': Config.setStatisticsFile(g.getOptarg()); break; case 't': Config.setEnableHtml(true); break; case 'b': Config.setHtmlRep(g.getOptarg()); break; case 'w': Config.setEnableWorstSignature(true); break; case 'f': Config.setInputFile(g.getOptarg()); break; case 'W': System.out.println("You tried a -W with an incorrect long option name"); break; case ':': System.out.println("You need an argument for option " + (char) g.getOptopt()); break; case '?': System.out.println("The option '" + (char) g.getOptopt() + "' is not valid"); break; default: System.out.println("getopt(): unknown option " + c); break; } } if(Config.getDictionary() == null) { Config.setDictionary("dico.txt"); } int from = g.getOptind(); String[] files = Config.getInputFiles(); int filesLength = (files==null)?0:files.length; classes = new JavaClass[args.length - from + filesLength]; for (i = 0; i < filesLength; i++) { classes[i] = (new ClassParser((String)files[i])).parse(); } for (int j = 0; j < args.length - from; j++) classes[i+j] = (new ClassParser(args[j + from])).parse(); ganalyser = new GlobalAnalyser(classes); ganalyser.analyse(); } catch (IOException e) { System.err.println(" E: File "+" does not exist or you don't have permission on it: "+e); e.printStackTrace(); error = 1; } catch (ClassNotFoundException e) { System.err.println("E: Internal error:"+e.toString()); error = 1; } time2 = System.currentTimeMillis(); System.out.println("Analyse took: "); System.out.println((time2 - time1) + "ms"); if (time2 - time1 < 1000) System.out.println((time2 - time1) + "ms"); else System.out.println(((time2 - time1) / 1000) + "s"); if (ClassAnalyser.memory < (1 << 10)) System.out.println(ClassAnalyser.memory + "octets"); else if (ClassAnalyser.memory < (1 << 20)) System.out.println((ClassAnalyser.memory >> 10) + "Ko"); else System.out.println((ClassAnalyser.memory >> 20) + "Mo"); Stats.printMemory(); System.exit(error); } }