Skip to content

Commit

Permalink
Improve handling of relative file paths in report files
Browse files Browse the repository at this point in the history
- Up to know we were stating in our [Wiki](https://github.com/SonarOpenCommunity/sonar-cxx/wiki/Troubleshooting-Reports): Relative paths in report files are always relative to the project base directory. Start relative paths always with .\ on Windows or ./ on Linux.
- relative paths starting with '..' were resolved to null in the past. "No file" results in adding an issue on project level (project issue). We replace now '..' with '.' (current directory=project base directory). This leads at least to an error message an that and the issue is not added to the project because typically no indexed file exists.
- The real problem is that tools generate reports with relative paths without defining which base directory is referred to. This problem remains and must be solved via the CI/CD and tool configuration.
- close #2741
  • Loading branch information
guwirth committed Sep 10, 2024
1 parent 95ea2ae commit 0ccc7bb
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,15 @@ public class CxxReportLocation {

public CxxReportLocation(@Nullable String file, @Nullable String line, @Nullable String column, String info) {
super();
// normalize file, removing double and single dot path steps => avoids duplicates

// Normalize file using separators in UNIX format, removing double and single dot path steps. This is to avoid
// duplicates in the issue containers because they are using the file as key. PathUtils.sanitize uses
// FilenameUtils.normalize internally, relative paths starting with a double dot will cause that path segment
// and the one before to be removed. If the double dot has no parent path segment to work with, null is returned.
// null would mean 'project issue' which is wrong in this context. To avoid this we replace '..\' with '.\'.
if (file != null && file.startsWith("..")) {
file = file.substring(1, file.length()); // fix #2747
}
this.file = PathUtils.sanitize(file);
this.line = line;
this.column = column;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* C++ Community Plugin (cxx plugin)
* Copyright (C) 2010-2023 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.cxx.utils;

import static org.assertj.core.api.Assertions.*;
import org.junit.jupiter.api.Test;

public class CxxReportLocationTest {

@Test
void testConstructor() {
var loc0 = new CxxReportLocation(null, null, null, "info");
assertThat(loc0.getFile()).isNull();
assertThat(loc0.getLine()).isNull();
assertThat(loc0.getColumn()).isNull();
assertThat(loc0.getInfo()).isEqualTo("info");
assertThat(loc0.toString()).isEqualTo("CxxReportLocation [file=null, line=null, column=null, info=info]");

var loc1 = new CxxReportLocation("file", "line", "column", "info");
assertThat(loc1.getFile()).isEqualTo("file");
assertThat(loc1.getLine()).isEqualTo("line");
assertThat(loc1.getColumn()).isEqualTo("column");
assertThat(loc1.getInfo()).isEqualTo("info");
assertThat(loc1.toString()).isEqualTo("CxxReportLocation [file=file, line=line, column=column, info=info]");
}

@Test
void testPathSanitize() {
var loc = new CxxReportLocation("file", null, null, "");

loc = new CxxReportLocation("/dir/File", null, null, "");
assertThat(loc.getFile()).isEqualTo("/dir/File");
loc = new CxxReportLocation("/dir/./File", null, null, "");
assertThat(loc.getFile()).isEqualTo("/dir/File");
loc = new CxxReportLocation("/dir/../File", null, null, "");
assertThat(loc.getFile()).isEqualTo("/File");
loc = new CxxReportLocation("dir/File", null, null, "");
assertThat(loc.getFile()).isEqualTo("dir/File");
loc = new CxxReportLocation("./dir/File", null, null, "");
assertThat(loc.getFile()).isEqualTo("dir/File");
loc = new CxxReportLocation("../dir/File", null, null, "");
assertThat(loc.getFile()).isEqualTo("dir/File");

loc = new CxxReportLocation("c:\\dir\\file.ext", null, null, "");
assertThat(loc.getFile()).isEqualTo("c:/dir/file.ext");
loc = new CxxReportLocation("C:\\dir\\.\\file.ext", null, null, "");
assertThat(loc.getFile()).isEqualTo("C:/dir/file.ext");
loc = new CxxReportLocation("c:\\dir\\..\\file.ext", null, null, "");
assertThat(loc.getFile()).isEqualTo("c:/file.ext");
loc = new CxxReportLocation("dir\\file.ext", null, null, "");
assertThat(loc.getFile()).isEqualTo("dir/file.ext");
loc = new CxxReportLocation(".\\dir\\file.ext", null, null, "");
assertThat(loc.getFile()).isEqualTo("dir/file.ext");
loc = new CxxReportLocation("..\\dir\\file.ext", null, null, "");
assertThat(loc.getFile()).isEqualTo("dir/file.ext");
}
}

0 comments on commit 0ccc7bb

Please sign in to comment.