Program: 3628
Project: 3628
Buggy source:
/** 
 * Constructs a FastClasspathScanner instance. You can pass a scanning specification to the constructor to describe what should be scanned. This prevents irrelevant classpath entries from being unecessarily scanned, which can be time-consuming. (Note that calling the constructor does not start the scan, you must separately call .scan() to perform the actual scan.)
 * @param scanSpec The constructor accepts a list of whitelisted package prefixes / jar names to scan, as well as blacklisted packages/jars not to scan, where blacklisted entries are prefixed with the '-' character. For example: new FastClasspathScanner("com.x"): limits scanning to the package com.x and its sub-packages in all jarfiles and all directory entries on the classpath. new FastClasspathScanner("com.x", "-com.x.y"): limits scanning to com.x and all sub-packages *except* com.x.y in all jars and directories on the classpath. new FastClasspathScanner("com.x", "-com.x.y", "jar:deploy.jar"): limits scanning to com.x and all its sub-packages except com.x.y, but only looks in jars named deploy.jar on the classpath. Note: 1. Whitelisting one or more jar entries prevents non-jar entries (directories) on the classpath from being scanned. 2. Only the leafname of a jarfile can be specified in a "jar:" or "-jar:" entry, so if there is a chance of conflict, make sure the jarfile's leaf name is unique. new FastClasspathScanner("com.x", "-jar:irrelevant.jar"): limits scanning to com.x and all sub-packages in all directories on the classpath, and in all jars except irrelevant.jar. (i.e. blacklisting a jarfile only excludes the specified jarfile, it doesn't prevent all directories from being scanned, as with whitelisting a jarfile.) new FastClasspathScanner("com.x", "jar:"): limits scanning to com.x and all sub-packages, but only looks in jarfiles on the classpath -- directories are not scanned. (i.e. "jar:" is a wildcard to indicate that all jars are whitelisted, and as in the example above, whitelisting jarfiles prevents non-jars (directories) from being scanned.) new FastClasspathScanner("com.x", "-jar:"): limits scanning to com.x and all sub-packages, but only looks in directories on the classpath -- jarfiles are not scanned. (i.e. "-jar:" is a wildcard to indicate that all jars are blacklisted.) new FastClasspathScanner(): If you don't specify any whitelisted package prefixes, all jarfiles and all directories on the classpath will be scanned. N.B. System, bootstrap and extension jarfiles (i.e. the JRE jarfiles) are never scanned.
 */
public FastClasspathScanner(final String... scanSpec){
  this.recursiveScanner=new RecursiveScanner(classpathFinder,scanSpec);
  final ArrayList<String> whitelistClassRefPrefix=new ArrayList<>();
  final ArrayList<String> blacklistClassRefPrefix=new ArrayList<>();
  if (scanSpec.length == 0 || (scanSpec.length == 1 && scanSpec[0].isEmpty())) {
    for (    String pkg : BLACKLISTED_PACKAGES) {
      String pkgPrefix=pkg + "String_Node_Str";
      blacklistedPackagePrefixes.add(pkgPrefix);
      blacklistClassRefPrefix.add(pkgPrefix.replace('.','/'));
    }
  }
 else {
    for (    final String spec : scanSpec) {
      if (!(spec.startsWith("String_Node_Str") || spec.startsWith("String_Node_Str"))) {
        if (spec.startsWith("String_Node_Str")) {
          String pkgPrefix=spec.substring(1) + "String_Node_Str";
          if (!pkgPrefix.isEmpty()) {
            blacklistedPackagePrefixes.add(pkgPrefix);
          }
          final String descriptor=pkgPrefix.replace('.','/');
          blacklistClassRefPrefix.add(descriptor);
        }
 else {
          String pkgPrefix=spec + "String_Node_Str";
          if (!spec.isEmpty()) {
            whitelistedPackagePrefixes.add(pkgPrefix);
          }
          final String descriptor=spec.replace('.','/');
          whitelistClassRefPrefix.add(descriptor);
        }
      }
    }
  }
  this.matchFilenameExtension("String_Node_Str",new FileMatchProcessor(){
    @Override public void processMatch(    final String relativePath,    final InputStream inputStream,    final int lengthBytes) throws IOException {
      if (!relativePathToClassInfo.containsKey(relativePath)) {
        final ClassInfo classInfo=ClassfileBinaryParser.readClassInfoFromClassfileHeader(relativePath,inputStream,classNameToStaticFieldnameToMatchProcessor,whitelistClassRefPrefix,blacklistClassRefPrefix);
        if (classInfo != null) {
          relativePathToClassInfo.put(relativePath,classInfo);
        }
      }
 else {
        if (verbose) {
          Log.log(relativePath.replace('/','.') + "String_Node_Str");
        }
      }
    }
  }
);
}

Fixed version (ground truth):
/** 
 * Constructs a FastClasspathScanner instance. You can pass a scanning specification to the constructor to describe what should be scanned. This prevents irrelevant classpath entries from being unecessarily scanned, which can be time-consuming. (Note that calling the constructor does not start the scan, you must separately call .scan() to perform the actual scan.)
 * @param scanSpec The constructor accepts a list of whitelisted package prefixes / jar names to scan, as well as blacklisted packages/jars not to scan, where blacklisted entries are prefixed with the '-' character. For example: new FastClasspathScanner("com.x"): limits scanning to the package com.x and its sub-packages in all jarfiles and all directory entries on the classpath. new FastClasspathScanner("com.x", "-com.x.y"): limits scanning to com.x and all sub-packages *except* com.x.y in all jars and directories on the classpath. new FastClasspathScanner("com.x", "-com.x.y", "jar:deploy.jar"): limits scanning to com.x and all its sub-packages except com.x.y, but only looks in jars named deploy.jar on the classpath. Note: 1. Whitelisting one or more jar entries prevents non-jar entries (directories) on the classpath from being scanned. 2. Only the leafname of a jarfile can be specified in a "jar:" or "-jar:" entry, so if there is a chance of conflict, make sure the jarfile's leaf name is unique. new FastClasspathScanner("com.x", "-jar:irrelevant.jar"): limits scanning to com.x and all sub-packages in all directories on the classpath, and in all jars except irrelevant.jar. (i.e. blacklisting a jarfile only excludes the specified jarfile, it doesn't prevent all directories from being scanned, as with whitelisting a jarfile.) new FastClasspathScanner("com.x", "jar:"): limits scanning to com.x and all sub-packages, but only looks in jarfiles on the classpath -- directories are not scanned. (i.e. "jar:" is a wildcard to indicate that all jars are whitelisted, and as in the example above, whitelisting jarfiles prevents non-jars (directories) from being scanned.) new FastClasspathScanner("com.x", "-jar:"): limits scanning to com.x and all sub-packages, but only looks in directories on the classpath -- jarfiles are not scanned. (i.e. "-jar:" is a wildcard to indicate that all jars are blacklisted.) new FastClasspathScanner(): If you don't specify any whitelisted package prefixes, all jarfiles and all directories on the classpath will be scanned. N.B. System, bootstrap and extension jarfiles (i.e. the JRE jarfiles) are never scanned.
 */
public FastClasspathScanner(final String... scanSpec){
  this.classpathFinder=new ClasspathFinder();
  if (FastClasspathScanner.verbose) {
    Log.log("String_Node_Str" + this.classpathFinder.getUniqueClasspathElements());
  }
  this.scanSpec=new ScanSpec(scanSpec);
  this.recursiveScanner=new RecursiveScanner(classpathFinder,this.scanSpec);
  final ScanSpec scanSpecParsed=this.scanSpec;
  this.matchFilenameExtension("String_Node_Str",new FileMatchProcessor(){
    @Override public void processMatch(    final String relativePath,    final InputStream inputStream,    final int lengthBytes) throws IOException {
      if (!relativePathToClassInfo.containsKey(relativePath)) {
        final ClassInfo classInfo=ClassfileBinaryParser.readClassInfoFromClassfileHeader(relativePath,inputStream,classNameToStaticFieldnameToMatchProcessor,scanSpecParsed);
        if (classInfo != null) {
          relativePathToClassInfo.put(relativePath,classInfo);
        }
      }
 else {
        if (verbose) {
          Log.log(relativePath.replace('/','.') + "String_Node_Str");
        }
      }
    }
  }
);
}