Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implements Dr Memory analysis #837

Merged
merged 5 commits into from
Apr 18, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,11 @@
import org.sonar.plugins.cxx.utils.CxxMetrics;

import com.google.common.collect.ImmutableList;

import org.sonar.api.config.Settings;
import org.sonar.plugins.cxx.coverage.CxxCoverageCache;
import org.sonar.plugins.cxx.drmemory.CxxDrMemoryRuleRepository;
import org.sonar.plugins.cxx.drmemory.CxxDrMemorySensor;
import org.sonar.plugins.dotnet.tests.CoverageAggregator;

/**
Expand Down Expand Up @@ -178,6 +181,14 @@ private static List<PropertyDefinition> codeAnalysisProperties() {
.subCategory(subcateg)
.index(4)
.build(),
PropertyDefinition.builder(CxxDrMemorySensor.REPORT_PATH_KEY)
.name("Dr Memory report(s)")
.description("Path to <a href='http://drmemory.org/'>Dr. Memory</a> reports(s), relative to projects root."
+ " Use <a href='https://ant.apache.org/manual/dirtasks.html'>Ant-style wildcards</a> if neccessary.")
.subCategory(subcateg)
.onQualifiers(Qualifiers.PROJECT, Qualifiers.MODULE)
.index(5)
.build(),
PropertyDefinition.builder(CxxPCLintSensor.REPORT_PATH_KEY)
.name("PC-lint report(s)")
.description("Path to <a href='http://www.gimpel.com/html/pcl.htm'>PC-lint</a> reports(s), relative to projects root."
Expand Down Expand Up @@ -415,6 +426,8 @@ public List getExtensions() {
l.add(CxxCppCheckSensor.class);
l.add(CxxPCLintRuleRepository.class);
l.add(CxxPCLintSensor.class);
l.add(CxxDrMemoryRuleRepository.class);
l.add(CxxDrMemorySensor.class);
l.add(CxxCompilerVcRuleRepository.class);
l.add(CxxCompilerGccRuleRepository.class);
l.add(CxxCompilerSensor.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Sonar C++ Plugin (Community)
* Copyright (C) 2010-2016 SonarOpenCommunity
* http://github.com/SonarOpenCommunity/sonar-cxx
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.plugins.cxx.drmemory;

import org.sonar.api.config.Settings;
import org.sonar.api.platform.ServerFileSystem;
import org.sonar.api.server.rule.RulesDefinitionXmlLoader;
import org.sonar.plugins.cxx.utils.CxxAbstractRuleRepository;

/**
* {@inheritDoc}
*/
public final class CxxDrMemoryRuleRepository extends CxxAbstractRuleRepository {

public static final String KEY = "drmemory";
public static final String CUSTOM_RULES_KEY = "sonar.cxx.drmemory.customRules";
private static final String NAME = "Dr Memory";

/**
* {@inheritDoc}
*/
public CxxDrMemoryRuleRepository(ServerFileSystem fileSystem, RulesDefinitionXmlLoader xmlRuleLoader, Settings settings) {
super(fileSystem, xmlRuleLoader, settings, KEY, NAME, CUSTOM_RULES_KEY);
}

@Override
protected String fileName() {
return "/drmemory.xml";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
* Sonar C++ Plugin (Community)
* Copyright (C) 2010-2016 SonarOpenCommunity
* http://github.com/SonarOpenCommunity/sonar-cxx
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.plugins.cxx.drmemory;

import java.io.File;
import java.io.IOException;

import org.sonar.api.batch.SensorContext;
import org.sonar.api.batch.fs.FileSystem;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.component.ResourcePerspectives;
import org.sonar.api.config.Settings;
import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.resources.Project;
import org.sonar.plugins.cxx.drmemory.DrMemoryParser.DrMemoryError;
import org.sonar.plugins.cxx.drmemory.DrMemoryParser.DrMemoryError.Location;
import org.sonar.plugins.cxx.utils.CxxMetrics;
import org.sonar.plugins.cxx.utils.CxxReportSensor;
import org.sonar.plugins.cxx.utils.CxxUtils;

/**
* Dr. Memory is a memory monitoring tool capable of identifying memory-related
* programming errors such as accesses of uninitialized memory, accesses to
* unaddressable memory (including outside of allocated heap units and heap
* underflow and overflow), accesses to freed memory, double frees, memory
* leaks, and (on Windows) handle leaks, GDI API usage errors, and accesses to
* un-reserved thread local storage slots. See also: http://drmemory.org
*
* @author asylvestre
*/
public class CxxDrMemorySensor extends CxxReportSensor {

public static final String REPORT_PATH_KEY = "sonar.cxx.drmemory.reportPath";
private final RulesProfile profile;

/**
* {@inheritDoc}
*/
public CxxDrMemorySensor(ResourcePerspectives perspectives,
Settings settings, FileSystem fs, RulesProfile profile) {
super(perspectives, settings, fs, CxxMetrics.DRMEMORY);
this.profile = profile;
}

/**
* {@inheritDoc}
*/
@Override
public boolean shouldExecuteOnProject(Project project) {
return super.shouldExecuteOnProject(project)
&& !profile.getActiveRulesByRepository(
CxxDrMemoryRuleRepository.KEY).isEmpty();
}

@Override
protected String reportPathKey() {
return REPORT_PATH_KEY;
}

@Override
protected void processReport(final Project project,
final SensorContext context, File report) {
CxxUtils.LOG.debug("Parsing 'Dr Memory' format");

try {
for (DrMemoryError error : DrMemoryParser.parse(report)) {
if (error.stackTrace.isEmpty()) {
saveUniqueViolation(project, context, CxxDrMemoryRuleRepository.KEY,
null, null,
error.type.getId(), error.message);
}
for (Location errorLocation : error.stackTrace) {
if (isFileInAnalysis(errorLocation)) {
saveUniqueViolation(project, context, CxxDrMemoryRuleRepository.KEY,
errorLocation.file, errorLocation.line.toString(),
error.type.getId(), error.message);
break;
}

}
}
} catch (IOException e) {
String msg = new StringBuilder()
.append("Cannot feed the data into sonar, details: '")
.append(e)
.append("'")
.toString();
throw new IllegalStateException(msg, e);
}
}

private boolean isFileInAnalysis(Location errorLocation) {
String root = fs.baseDir().getAbsolutePath();
String normalPath = CxxUtils.normalizePathFull(errorLocation.file, root);
InputFile inputFile = fs.inputFile(fs.predicates().is(new File(normalPath)));
return inputFile != null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
/*
* Sonar C++ Plugin (Community)
* Copyright (C) 2010-2016 SonarOpenCommunity
* http://github.com/SonarOpenCommunity/sonar-cxx
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.plugins.cxx.drmemory;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.sonar.plugins.cxx.drmemory.DrMemoryParser.DrMemoryError.Location;

public class DrMemoryParser {

public static enum DrMemoryErrorType {
UNADRESSABLE_ACCESS("UnadressableAccess", "UNADDRESSABLE ACCESS"),
UNINITIALIZE_READ("UninitializedRead", "UNINITIALIZED READ"),
INVALID_HEAP_ARGUMENT("InvalidHeapArgument", "INVALID HEAP ARGUMENT"),
GDI_USAGE_ERROR("GdiUsageError", "GDI Usage Error"),
HANDLE_LEAK("HandleLeak", "HANDLE LEAK"),
WARNING("DrMemoryWarning", "WARNING"),
POSSIBLE_LEAK("PossibleMemoryLeak", "POSSIBLE LEAK"),
LEAK("MemoryLeak", "LEAK"),
UNRECOGNIZED("Dr Memory unrecognized error", "");

private String id;
private String title;

DrMemoryErrorType(String id, String title) {
this.id = id;
this.title = title;
}

public String getId() {
return id;
}

public String getTitle() {
return title;
}
}



public static class DrMemoryError {

public static class Location {
public String file = "";
public Integer line;
}

public DrMemoryErrorType type = DrMemoryErrorType.UNRECOGNIZED;
public List<Location> stackTrace = new ArrayList<Location>();
public String message = "";
}


private DrMemoryParser() {
}

public static final Pattern rx_message_finder = Pattern.compile( "^Error #\\d+:(.*)");
public static final Pattern rx_file_finder = Pattern.compile( "^.*\\[(.*):(\\d+)\\]$");

public static final int __TOP_COUNT = 4;

public static List<DrMemoryError> parse( File file ) throws IOException {

List<DrMemoryError> result = new ArrayList<DrMemoryError>();

List<String> elements = getElements(file);

for (String element : elements) {
Matcher m = rx_message_finder.matcher( element );

if( m.find() ) {
DrMemoryError error = new DrMemoryError();
error.type = extractErrorType(m.group(1));
String elementSplitted[] = element.split("\\r?\\n");
error.message = elementSplitted[0];
for (String elementPart : elementSplitted) {
Matcher locationMatcher = rx_file_finder.matcher( elementPart );
if (locationMatcher.find()) {
Location location = new Location();
location.file = locationMatcher.group( 1 );
location.line = Integer.parseInt(locationMatcher.group( 2 ));
error.stackTrace.add(location);
}
}
result.add(error);

}
}

return result;
}


private static DrMemoryErrorType extractErrorType(String title) {
String cleanedTitle = clean(title);
for (DrMemoryErrorType drMemoryErrorType : DrMemoryErrorType.values()) {
if (cleanedTitle.startsWith(drMemoryErrorType.getTitle()))
return drMemoryErrorType;
}
return DrMemoryErrorType.UNRECOGNIZED;
}


private static String clean(String title) {
return title.trim();
}


public static List<String> getElements( File file ) throws IOException {
FileReader fr = new FileReader( file );
BufferedReader br = new BufferedReader( fr );
List<String> list = new ArrayList<String>();
StringBuilder sb = new StringBuilder();
String line;
int cnt = 0;
while( ( line = br.readLine() ) != null ) {
if( cnt > ( __TOP_COUNT ) ) {

if( line.matches( "^\\s*$" ) ) {
list.add( sb.toString() );
sb.setLength( 0 );

} else {
sb.append( line + "\n" );
}
}

cnt++;
}

if( sb.length() > 0 ) {
list.add( sb.toString() );
}

br.close();

return list;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Sonar C++ Plugin (Community)
* Copyright (C) 2010-2016 SonarOpenCommunity
* http://github.com/SonarOpenCommunity/sonar-cxx
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

/**
* Package with sensor to evaluate Dr Memrory specific results files.
*/
@ParametersAreNonnullByDefault
package org.sonar.plugins.cxx.drmemory;

import javax.annotation.ParametersAreNonnullByDefault;
Loading