[Fb-contrib-commit] SF.net SVN: fb-contrib: [816] trunk/fb-contrib/src/com/mebigfatguy/ fbcontrib/
Brought to you by:
dbrosius
From: <dbr...@us...> - 2007-02-01 09:38:23
|
Revision: 816 http://svn.sourceforge.net/fb-contrib/?rev=816&view=rev Author: dbrosius Date: 2007-02-01 01:38:22 -0800 (Thu, 01 Feb 2007) Log Message: ----------- getting closer Modified Paths: -------------- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/SuspiciousJDKVersionUse.java Modified: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/SuspiciousJDKVersionUse.java =================================================================== --- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/SuspiciousJDKVersionUse.java 2007-02-01 08:28:00 UTC (rev 815) +++ trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/SuspiciousJDKVersionUse.java 2007-02-01 09:38:22 UTC (rev 816) @@ -19,8 +19,8 @@ package com.mebigfatguy.fbcontrib.detect; import java.io.File; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; +import java.io.IOException; +import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; @@ -35,6 +35,7 @@ import org.apache.bcel.Constants; import org.apache.bcel.classfile.ClassParser; import org.apache.bcel.classfile.JavaClass; +import org.apache.bcel.classfile.Method; import com.mebigfatguy.fbcontrib.utils.Integer14; @@ -47,18 +48,20 @@ { private static final Map<Integer, String> verRegEx = new HashMap<Integer, String>(); static { - verRegEx.put(Integer14.valueOf(Constants.MAJOR_1_1), "(jdk|jre)1.1"); - verRegEx.put(Integer14.valueOf(Constants.MAJOR_1_2), "(jdk|jre)1.2"); - verRegEx.put(Integer14.valueOf(Constants.MAJOR_1_3), "(jdk|jre)1.3"); - verRegEx.put(Integer14.valueOf(Constants.MAJOR_1_4), "(jdk|jre)1.4"); - verRegEx.put(Integer14.valueOf(Constants.MAJOR_1_5), "(jdk|jre)1.5"); - verRegEx.put(Integer14.valueOf(50), "jdk1.6"); + verRegEx.put(Integer14.valueOf(Constants.MAJOR_1_1), "(jdk|j2?re)1.1"); + verRegEx.put(Integer14.valueOf(Constants.MAJOR_1_2), "(jdk|j2?re)1.2"); + verRegEx.put(Integer14.valueOf(Constants.MAJOR_1_3), "(jdk|j2?re)1.3"); + verRegEx.put(Integer14.valueOf(Constants.MAJOR_1_4), "(jdk|j2?re)1.4"); + verRegEx.put(Integer14.valueOf(Constants.MAJOR_1_5), "(jdk|j2?re)1.5"); + verRegEx.put(Integer14.valueOf(50), "(jdk|j2?re)1.6"); } private static final Pattern jarPattern = Pattern.compile("jar:file:/*([^!]*)"); private Map<String, File> versionPaths; private Map<Integer, Map<String, Set<String>>> validMethodsByVersion; + private Map<String, String> superNames; private File jdksRoot = null; + JavaClass cls; private URLClassLoader jdkLoader; private Integer clsMajorVersion; private BugReporter bugReporter; @@ -67,25 +70,23 @@ this.bugReporter = bugReporter; versionPaths = new HashMap<String, File>(); validMethodsByVersion = new HashMap<Integer, Map<String, Set<String>>>(); + superNames = new HashMap<String, String>(); } - /* - * Use BCEL to load class, not URLClassLoader - * - * ClassParser parser = new ClassParser(is, className); - * JavaClass clazz = parser.parse(); - */ @Override public void visitClassContext(ClassContext classContext) { try { - JavaClass cls = classContext.getJavaClass(); + cls = classContext.getJavaClass(); clsMajorVersion = Integer14.valueOf(cls.getMajor()); File rtJar = getRTJarFile(cls); - jdkLoader = new URLClassLoader(new URL[] {rtJar.toURL()}); - super.visitClassContext(classContext); + if (rtJar != null) { + jdkLoader = new URLClassLoader(new URL[] {rtJar.toURL()}); + super.visitClassContext(classContext); + } } catch (MalformedURLException mue) { //Hmm, what to do } finally { + cls = null; jdkLoader = null; } } @@ -94,6 +95,8 @@ public void sawOpcode(int seen) { String clsName = null; + InputStream is = null; + try { if ((seen == INVOKEVIRTUAL) || (seen == INVOKEINTERFACE) @@ -107,42 +110,70 @@ validMethods = new HashMap<String, Set<String>>(); validMethodsByVersion.put(clsMajorVersion, validMethods); } - Set<String> methodInfos = validMethods.get(clsName); - if (methodInfos == null) { - Class c = jdkLoader.loadClass(clsName.replace('/', '.')); - Method[] methods = c.getDeclaredMethods(); - - methodInfos = new HashSet<String>(); - validMethods.put(clsName, methodInfos); - - for (Method m : methods) { - if ((m.getModifiers() & Modifier.PRIVATE) == 0) { - String[] mi = m.toString().split("\\(\\)"); - int dotPos = mi[0].lastIndexOf('.'); - String name = mi[0].substring(dotPos+1); - String sig; - if (mi.length == 1) - sig = "()"; - else { - if (mi[1].trim().startsWith("throws")) - sig = "()"; - else - sig = "(" + mi[1] + ")"; - } - methodInfos.add(name + sig); - } - } + + if (!isValid(validMethods, clsName)) { + bugReporter.reportBug(new BugInstance(this, "SJVU_SUSPICIOUS_JDK_VERSION_USE", HIGH_PRIORITY) + .addClass(this) + .addMethod(this) + .addSourceLine(this)); } + } + } + } catch (Exception e) { + // Hmm what to do + } finally { + if (is != null) { + try { + is.close(); + } catch (IOException ioe) { + } + } + } + } + + private boolean isValid(Map<String, Set<String>> validMethods, String clsName) throws IOException, ClassNotFoundException { + InputStream is = null; + + try { + Set<String> methodInfos = validMethods.get(clsName); + if (methodInfos == null) { + is = jdkLoader.getResourceAsStream(clsName + ".class"); + if (is != null) { + ClassParser parser = new ClassParser(is, clsName); + JavaClass calledClass = parser.parse(); + superNames.put(clsName, calledClass.getSuperclassName().replace('.', '/')); + Method[] methods = calledClass.getMethods(); + methodInfos = new HashSet<String>(); + validMethods.put(clsName, methodInfos); + + for (Method m : methods) { + if (!m.isPrivate()) + methodInfos.add(m.getName() + m.getSignature()); + } + } + else { + return true; + } + } - } catch (ClassNotFoundException cnfe) { - if (clsName.startsWith("java/")) { - bugReporter.reportBug(new BugInstance(this, "SJVU_SUSPICIOUS_JDK_VERSION_USE", NORMAL_PRIORITY) - .addClass(this) - .addMethod(this) - .addSourceLine(this)); + + String wantedMethod = getNameConstantOperand() + getSigConstantOperand(); + if (methodInfos.contains(wantedMethod)) + return true; + else if ("java/lang/Object".equals(clsName)) + return false; + else + return isValid(validMethods, superNames.get(clsName)); + } + finally { + if (is != null) { + try { + is.close(); + } catch (IOException ioe) { + } } } } @@ -175,25 +206,26 @@ return null; jdksRoot = new File(URLDecoder.decode(jdksRoot.getParentFile().getPath())); - - File[] possibleJdks = jdksRoot.listFiles(); - for (File possibleJdk : possibleJdks) { - m = verPat.matcher(possibleJdk.getName()); - if (m.find()) { - File wantedRtJar = new File(possibleJdk, "lib/rt.jar"); - if (!wantedRtJar.exists()) { - wantedRtJar = new File(possibleJdk, "jre/lib/rt.jar"); - if (!wantedRtJar.exists()) - return null; - } - versionPaths.put(versionStr, wantedRtJar); - return wantedRtJar; - } - } } } } + File[] possibleJdks = jdksRoot.listFiles(); + for (File possibleJdk : possibleJdks) { + Pattern verPat = Pattern.compile(versionStr); + Matcher m = verPat.matcher(possibleJdk.getName()); + if (m.find()) { + File wantedRtJar = new File(possibleJdk, "lib/rt.jar"); + if (!wantedRtJar.exists()) { + wantedRtJar = new File(possibleJdk, "jre/lib/rt.jar"); + if (!wantedRtJar.exists()) + return null; + } + versionPaths.put(versionStr, wantedRtJar); + return wantedRtJar; + } + } + return null; } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |