4444import java .util .TreeMap ;
4545import java .util .TreeSet ;
4646
47- import javax .resource .NotSupportedException ;
4847import javax .xml .parsers .DocumentBuilder ;
4948import javax .xml .parsers .DocumentBuilderFactory ;
5049
6766import org .owasp .benchmark .score .parsers .NoisyCricketReader ;
6867import org .owasp .benchmark .score .parsers .Rapid7Reader ;
6968import org .owasp .benchmark .score .parsers .SonarQubeReader ;
69+ import org .owasp .benchmark .score .parsers .SourceMeterReader ;
7070import org .owasp .benchmark .score .parsers .TestCaseResult ;
7171import org .owasp .benchmark .score .parsers .TestResults ;
7272import org .owasp .benchmark .score .parsers .VeracodeReader ;
7373import org .owasp .benchmark .score .parsers .WebInspectReader ;
74+ import org .owasp .benchmark .score .parsers .XanitizerReader ;
7475import org .owasp .benchmark .score .parsers .ZapReader ;
7576import org .owasp .benchmark .score .report .Report ;
7677import org .owasp .benchmark .score .report .ScatterHome ;
@@ -387,7 +388,8 @@ private static void process(File f, TestResults expectedResults, Set<Report> too
387388 //System.out.println("Computed actual results for tool: " + actualResults.getTool());
388389
389390 if ( expectedResults != null && actualResults != null ) {
390- // note: side effect is that "pass/fail" value is set for each expected result
391+ // note: side effect is that "pass/fail" value is set for each expected result so it
392+ // can be used to produce scorecard for this tool
391393 analyze ( expectedResults , actualResults );
392394
393395 // Produce a .csv results file of the actual results, except if its a commercial tool,
@@ -619,13 +621,23 @@ else if ( filename.endsWith(".json" ) ) {
619621 }
620622 }
621623
624+ else if ( filename .endsWith ( ".txt" ) ) {
625+ String line1 = getLine ( fileToParse , 0 );
626+ if ( line1 .startsWith ( "Possible " ) ) {
627+ tr = new SourceMeterReader ().parse ( fileToParse );
628+ }
629+ }
622630 else if ( filename .endsWith ( ".xml" ) ) {
623631 String line1 = getLine ( fileToParse , 0 );
624632 String line2 = getLine ( fileToParse , 1 );
625633 if ( line2 .startsWith ( "<pmd" )) {
626634 tr = new PMDReader ().parse ( fileToParse );
627635 }
628636
637+ else if (line2 .startsWith ("<XanitizerFindingsList" )) {
638+ tr = new XanitizerReader ().parse (fileToParse );
639+ }
640+
629641 else if ( line2 .startsWith ( "<BugCollection" )) {
630642 tr = new FindbugsReader ().parse ( fileToParse );
631643
@@ -890,7 +902,12 @@ private static TestResults readExpectedResults(File f1) throws Exception {
890902 line = fr .readLine ();
891903 reading = line != null ;
892904 if ( reading ) {
893- String [] parts = line .split ("," );
905+ // Normally, each line contains: test name, category, real vulnerability, cwe #
906+
907+ // String[] parts = line.split(",");
908+ // regex from http://stackoverflow.com/questions/1757065/java-splitting-a-comma-separated-string-but-ignoring-commas-in-quotes
909+ // This regex needed because some 'full details' entries contain comma's inside quoted strings
910+ String [] parts = line .split (",(?=([^\" ]*\" [^\" ]*\" )*[^\" ]*$)" );
894911 if ( parts [0 ] != null && parts [0 ].startsWith ("Bench" ) ) {
895912 TestCaseResult tcr = new TestCaseResult ();
896913 tcr .setTestCaseName (parts [0 ]);
@@ -901,6 +918,16 @@ private static TestResults readExpectedResults(File f1) throws Exception {
901918 String tcname = parts [0 ].substring ( "BenchmarkTest" .length () );
902919 tcr .setNumber ( Integer .parseInt (tcname ));
903920
921+ // Handle situation where expected results has full details
922+ // Sometimes, it also has: source, data flow, data flow filename, sink
923+
924+ if (parts .length > 4 ) {
925+ tcr .setSource (parts [4 ]);
926+ tcr .setDataFlow (parts [5 ]);
927+ tcr .setDataFlowFile (parts [6 ]);
928+ tcr .setSink (parts [7 ]);
929+ }
930+
904931 tr .put ( tcr );
905932 }
906933 }
@@ -932,30 +959,37 @@ private static String produceResultsFile( TestResults actual ) {
932959 FileOutputStream fos = new FileOutputStream (resultsFile , false );
933960 ps = new PrintStream (fos );
934961
935- // Write actual results header
936- ps .print ("# test name, category, real vulnerability, CWE, identified by tool, pass/fail" );
962+ Set <Integer > testCaseKeys = actual .keySet ();
937963
938- // Add the version # inside the file as well
939- ps .print (", Benchmark version: " + benchmarkVersion );
964+ boolean fulldetails = (actual .get (testCaseKeys .iterator ().next ()).get (0 ).getSource () != null );
965+
966+ // Write actual results header
967+ ps .print ("# test name, category, CWE, " );
968+ if (fulldetails ) ps .print ("source, data flow, data flow filename, sink, " );
969+ ps .print ("real vulnerability, identified by tool, pass/fail, Benchmark version: " + benchmarkVersion );
940970
941971 // Append the date YYYY-MM-DD to the header in each .csv file
942972 Calendar c = Calendar .getInstance ();
943973 String s = String .format ("%1$tY-%1$tm-%1$te" , c );
944974 ps .println (", Actual results generated: " + s );
945975
946- Set <Integer > testCaseKeys = actual .keySet ();
947-
948976 for (Integer expectedResultsKey : testCaseKeys ) {
949977 // Write meta data to file here.
950978 TestCaseResult actualResult = actual .get (expectedResultsKey .intValue ()).get (0 );
951979 ps .print (actualResult .getName ());
952980 ps .print (", " + actualResult .getCategory ());
981+ ps .print (", " + actualResult .getCWE ());
982+ if (fulldetails ) {
983+ ps .print ("," + actualResult .getSource ());
984+ ps .print ("," + actualResult .getDataFlow ());
985+ ps .print (", " + actualResult .getDataFlowFile ());
986+ ps .print ("," + actualResult .getSink ());
987+ }
953988 boolean isreal = actualResult .isReal ();
954989 ps .print (", " + isreal );
955- ps .print (", " + actualResult .getCWE ());
956990 boolean passed = actualResult .isPassed ();
957991 boolean toolresult = !(isreal ^passed );
958- ps .print (", " + toolresult );
992+ ps .print (", " + toolresult );
959993 ps .println (", " + (passed ? "pass" : "fail" ));
960994 }
961995
0 commit comments