Skip to content

Commit

Permalink
Merge pull request #1575 from ivangalkin/fix_1574
Browse files Browse the repository at this point in the history
path normalization / absolutization is not allowed to use File::getCanonicalPath()
  • Loading branch information
guwirth authored Oct 23, 2018
2 parents 1919e64 + f7c06dd commit bb69606
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 90 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import javax.xml.stream.XMLStreamException;
import org.codehaus.staxmate.in.SMHierarchicCursor;
import org.codehaus.staxmate.in.SMInputCursor;
import org.sonar.api.batch.sensor.SensorContext;
import org.sonar.api.utils.PathUtils;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
Expand All @@ -45,14 +44,14 @@ public class BullseyeParser extends CxxCoverageParser {
private static int totalcoveredconditions;

public BullseyeParser() {
// no operation but necessary for list of coverage parsers
// no operation but necessary for list of coverage parsers
}

/**
* {@inheritDoc}
*/
@Override
public void processReport(final SensorContext context, File report, final Map<String, CoverageMeasures> coverageData)
public void processReport(File report, final Map<String, CoverageMeasures> coverageData)
throws XMLStreamException {
LOG.debug("Parsing 'Bullseye' format");
StaxParser topLevelparser = new StaxParser(new StaxParser.XmlStreamHandler() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,17 @@
package org.sonar.cxx.sensors.coverage;

import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.stream.XMLStreamException;
import org.codehaus.staxmate.in.SMHierarchicCursor;
import org.codehaus.staxmate.in.SMInputCursor;
import org.sonar.api.batch.sensor.SensorContext;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.cxx.sensors.utils.CxxUtils;
import org.sonar.cxx.sensors.utils.StaxParser;

/**
Expand All @@ -39,7 +39,7 @@
public class CoberturaParser extends CxxCoverageParser {

private static final Logger LOG = Loggers.get(CoberturaParser.class);
private String baseDir;
private Optional<Path> baseDir;
private static final Pattern conditionsPattern = Pattern.compile("\\((.*?)\\)");

public CoberturaParser() {
Expand All @@ -50,10 +50,10 @@ public CoberturaParser() {
* {@inheritDoc}
*/
@Override
public void processReport(final SensorContext context, File report, final Map<String, CoverageMeasures> coverageData)
public void processReport(File report, final Map<String, CoverageMeasures> coverageData)
throws XMLStreamException {
LOG.debug("Parsing 'Cobertura' format");
baseDir = context.fileSystem().baseDir().getAbsolutePath();
baseDir = Optional.empty();

StaxParser sourceParser = new StaxParser((SMHierarchicCursor rootCursor) -> {
rootCursor.advance();
Expand All @@ -63,7 +63,7 @@ public void processReport(final SensorContext context, File report, final Map<St

StaxParser packageParser = new StaxParser((SMHierarchicCursor rootCursor) -> {
rootCursor.advance();
collectPackageMeasures(baseDir, rootCursor.descendantElementCursor("package"), coverageData);
collectPackageMeasures(rootCursor.descendantElementCursor("package"), coverageData);
});
packageParser.parse(report);
}
Expand All @@ -72,33 +72,37 @@ private void readBaseDir(SMInputCursor source) throws XMLStreamException {
while (source.getNext() != null) {
String sourceValue = source.getElemStringValue().trim();
if (!sourceValue.isEmpty()) {
baseDir = Paths.get(baseDir).resolve(sourceValue).normalize().toString();
baseDir = Optional.of(Paths.get(sourceValue));
break;
}
}
}

private static void collectPackageMeasures(final String baseDir, SMInputCursor pack,
Map<String, CoverageMeasures> coverageData)
throws XMLStreamException {
private void collectPackageMeasures(SMInputCursor pack, Map<String, CoverageMeasures> coverageData)
throws XMLStreamException {
while (pack.getNext() != null) {
collectFileMeasures(baseDir, pack.descendantElementCursor("class"), coverageData);
collectFileMeasures(pack.descendantElementCursor("class"), coverageData);
}
}

private static void collectFileMeasures(final String baseDir, SMInputCursor clazz,
Map<String, CoverageMeasures> coverageData)
throws XMLStreamException {
private String buildPath(String filename) {
Path result = Paths.get(filename);
if (baseDir.isPresent()) {
result = baseDir.get().resolve(result);
}
return result.normalize().toString();
}

private void collectFileMeasures(SMInputCursor clazz, Map<String, CoverageMeasures> coverageData)
throws XMLStreamException {
while (clazz.getNext() != null) {
String normalPath = CxxUtils.normalizePathFull(clazz.getAttrValue("filename"), baseDir);
if (normalPath != null) {
CoverageMeasures builder = coverageData.get(normalPath);
if (builder == null) {
builder = CoverageMeasures.create();
coverageData.put(normalPath, builder);
}
collectFileData(clazz, builder);
String normalPath = buildPath(clazz.getAttrValue("filename"));
CoverageMeasures builder = coverageData.get(normalPath);
if (builder == null) {
builder = CoverageMeasures.create();
coverageData.put(normalPath, builder);
}
collectFileData(clazz, builder);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,33 @@

import java.io.File;
import java.util.Map;

import javax.xml.stream.XMLStreamException;
import org.sonar.api.batch.sensor.SensorContext;

/**
* The interface a coverage report parser has to implement in order to be used by CxxCoverageSensor
* The interface a coverage report parser has to implement in order to be used
* by CxxCoverageSensor
*/
public interface CoverageParser {

/**
* Parses the given report and stores the results in the according builder
*
* @param context of sensor
* @param report with coverage data
* @param coverageData A Map mapping source file names to coverage measures. Has to be used to store the results into.
* @throws XMLStreamException javax.xml.stream.XMLStreamException
* @param context
* of sensor
* @param report
* with coverage data
* @param coverageData
* A Map mapping source file names to coverage measures. Has to be
* used to store the results into. Source file names might be
* relative. In such case they will be resolved against the base
* directory of SonarQube module/project.<br>
*
* <b>ATTENTION!</b> This map is shared between modules in
* multi-module projects. Don't try to resolve paths against some
* specific module!
* @throws XMLStreamException
* javax.xml.stream.XMLStreamException
*/
void processReport(final SensorContext context, File report, Map<String, CoverageMeasures> coverageData)
throws XMLStreamException;
void processReport(File report, Map<String, CoverageMeasures> coverageData) throws XMLStreamException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -100,20 +100,20 @@ public void execute(SensorContext context) {
}

List<File> reports = getReports(context.config(), context.fileSystem().baseDir(), getReportPathKey());
coverageMeasures = processReports(context, reports, this.cache.unitCoverageCache());
coverageMeasures = processReports(reports, this.cache.unitCoverageCache());
saveMeasures(context, coverageMeasures);
}
}

private Map<String, CoverageMeasures> processReports(final SensorContext context, List<File> reports,
Map<String, Map<String, CoverageMeasures>> cacheCov) {
private Map<String, CoverageMeasures> processReports(List<File> reports,
Map<String, Map<String, CoverageMeasures>> cacheCov) {
Map<String, CoverageMeasures> measuresTotal = new HashMap<>();

for (File report : reports) {
if (!cacheCov.containsKey(report.getAbsolutePath())) {
for (CoverageParser parser : parsers) {
try {
parseCoverageReport(parser, context, report, measuresTotal);
parseCoverageReport(parser, report, measuresTotal);
if (LOG.isDebugEnabled()) {
LOG.debug("cached measures for '{}' : current cache content data = '{}'", report.getAbsolutePath(),
cacheCov.size());
Expand Down Expand Up @@ -145,11 +145,11 @@ private Map<String, CoverageMeasures> processReports(final SensorContext context
* @param measuresTotal
* @return true if report was parsed and results are available otherwise false
*/
private static void parseCoverageReport(CoverageParser parser, final SensorContext context, File report,
Map<String, CoverageMeasures> measuresTotal) {
private static void parseCoverageReport(CoverageParser parser, File report,
Map<String, CoverageMeasures> measuresTotal) {
Map<String, CoverageMeasures> measuresForReport = new HashMap<>();
try {
parser.processReport(context, report, measuresForReport);
parser.processReport(report, measuresForReport);
} catch (XMLStreamException e) {
throw new EmptyReportException("Coverage report" + report + "cannot be parsed by" + parser, e);
}
Expand All @@ -165,9 +165,8 @@ private static void parseCoverageReport(CoverageParser parser, final SensorConte
private void saveMeasures(SensorContext context,
Map<String, CoverageMeasures> coverageMeasures) {
for (Map.Entry<String, CoverageMeasures> entry : coverageMeasures.entrySet()) {
String filePath = PathUtils.sanitize(entry.getKey());
final String filePath = PathUtils.sanitize(entry.getKey());
if (filePath != null) {
filePath = CxxUtils.normalizePathFull(filePath, context.fileSystem().baseDir().getAbsolutePath());
InputFile cxxFile = context.fileSystem().inputFile(context.fileSystem().predicates().hasPath(filePath));
if (LOG.isDebugEnabled()) {
LOG.debug("save coverage measure for file: '{}' cxxFile = '{}'", filePath, cxxFile);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@

import org.apache.commons.io.FilenameUtils;

import org.sonar.api.batch.sensor.SensorContext;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;

Expand All @@ -51,25 +50,25 @@
public class TestwellCtcTxtParser extends CxxCoverageParser {

private static final Logger LOG = Loggers.get(TestwellCtcTxtParser.class);

private Scanner scanner;

private static final int FROM_START = 0;
private static final int CONDS_FALSE = 1;
private static final int CONDS_TRUE = 2;
private static final int LINE_NR_GROUP = 3;



public TestwellCtcTxtParser() {
// no operation but necessary for list of coverage parsers
// no operation but necessary for list of coverage parsers
}

/**
* {@inheritDoc}
*/
@Override
public void processReport(final SensorContext context, File report, final Map<String, CoverageMeasures> coverageData) {
public void processReport(File report, final Map<String, CoverageMeasures> coverageData) {
LOG.debug("Parsing 'Testwell CTC++' textual format");

try (Scanner s = new Scanner(report).useDelimiter(SECTION_SEP)) {
Expand Down Expand Up @@ -122,7 +121,7 @@ private void addLines(File file, final Map<String, CoverageMeasures> coverageDat

private void parseLineSection(CoverageMeasures coverageMeasures, String nextLine) {
LOG.debug("Found line section...");

Matcher lineMatcher = LINE_RESULT.matcher(nextLine);
if (lineMatcher.find(FROM_START)) {
addEachLine(coverageMeasures, lineMatcher);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import javax.xml.stream.XMLStreamException;
import org.codehaus.staxmate.in.SMHierarchicCursor;
import org.codehaus.staxmate.in.SMInputCursor;
import org.sonar.api.batch.sensor.SensorContext;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.cxx.sensors.utils.StaxParser;
Expand All @@ -37,14 +36,14 @@ public class VisualStudioParser extends CxxCoverageParser {
private static final Logger LOG = Loggers.get(VisualStudioParser.class);

public VisualStudioParser() {
// no operation but necessary for list of coverage parsers
// no operation but necessary for list of coverage parsers
}

/**
* {@inheritDoc}
*/
@Override
public void processReport(final SensorContext context, File report, final Map<String, CoverageMeasures> coverageData)
public void processReport(File report, final Map<String, CoverageMeasures> coverageData)
throws XMLStreamException {
LOG.debug("Parsing 'Visual Studio' format");
StaxParser parser = new StaxParser(new StaxParser.XmlStreamHandler() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ public void execute(SensorContext context) {
LOG.info("Searching reports by relative path with basedir '{}' and search prop '{}'",
context.fileSystem().baseDir(), getReportPathKey());
List<File> reports = getReports(context.config(), context.fileSystem().baseDir(), getReportPathKey());
notFoundFiles.clear();
violationsPerFileCount.clear();
violationsPerModuleCount = 0;

Expand Down Expand Up @@ -158,15 +159,14 @@ public void saveUniqueViolation(SensorContext sensorContext, CxxReportIssue issu
}

public InputFile getInputFileIfInProject(SensorContext sensorContext, String path) {
String root = sensorContext.fileSystem().baseDir().getAbsolutePath();
String normalPath = CxxUtils.normalizePathFull(path, root);
if (normalPath == null || notFoundFiles.contains(normalPath)) {
if (notFoundFiles.contains(path)) {
return null;
}
InputFile inputFile = sensorContext.fileSystem()
.inputFile(sensorContext.fileSystem().predicates().hasAbsolutePath(normalPath));
final InputFile inputFile = sensorContext.fileSystem().inputFile(sensorContext.fileSystem().predicates().hasPath(path));
if (inputFile == null) {
notFoundFiles.add(normalPath);
LOG.debug("Path '{}' couldn't be found in module '{}' base dir '{}'", path, sensorContext.module().key(),
sensorContext.fileSystem().baseDir());
notFoundFiles.add(path);
}
return inputFile;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,38 +48,6 @@ private CxxUtils() {
// only static methods
}

/**
* Normalize the given path to pass it to sonar. Return null if normalization has failed.
*
* @param filename
* @return normalized path
*/
public static String normalizePath(String filename) {
try {
return new File(filename).getCanonicalPath();
} catch (java.io.IOException e) {
LOG.error("path normalizing of '{}' failed: '{}'", filename, e);
return null;
}
}

/**
* @param filename
* @param baseDir
* @return returns case sensitive full path
*/
public static String normalizePathFull(String filename, String baseDir) {
File targetfile = new java.io.File(filename.trim());
String filePath;
if (targetfile.isAbsolute()) {
filePath = normalizePath(filename);
} else {
// RATS, CppCheck and Vera++ provide names like './file.cpp' - add input folder for index check
filePath = normalizePath(baseDir + File.separator + filename);
}
return filePath;
}

/**
* transformFile
*
Expand Down

0 comments on commit bb69606

Please sign in to comment.